From 995742ff7af7c0755f541e9f2524bcae5c2265b0 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Wed, 1 Jan 2025 18:52:21 +0200 Subject: [PATCH 001/189] check for multi edges on create instead per render --- app/components/graphView.tsx | 21 ------------ app/components/model.ts | 66 +++++++++++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 26 deletions(-) diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index b754fd82..66d75a2d 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -221,20 +221,7 @@ export default function GraphView({ if (!start.x || !start.y || !end.x || !end.y) return - const sameNodesLinks = graph.Elements.links.filter(l => (l.source.id === start.id && l.target.id === end.id) || (l.target.id === start.id && l.source.id === end.id)) - const index = sameNodesLinks.findIndex(l => l.id === link.id) || 0 - const even = index % 2 === 0 - let curve - if (start.id === end.id) { - if (even) { - curve = Math.floor(-(index / 2)) - 3 - } else { - curve = Math.floor((index + 1) / 2) + 2 - } - - link.curve = curve * 0.1 - const radius = NODE_SIZE * link.curve * 6.2; const angleOffset = -Math.PI / 4; // 45 degrees offset for text alignment const textX = start.x + radius * Math.cos(angleOffset); @@ -244,14 +231,6 @@ export default function GraphView({ ctx.translate(textX, textY); ctx.rotate(-angleOffset); } else { - if (even) { - curve = Math.floor(-(index / 2)) - } else { - curve = Math.floor((index + 1) / 2) - } - - link.curve = curve * 0.1 - const midX = (start.x + end.x) / 2 + (end.y - start.y) * (link.curve / 2); const midY = (start.y + end.y) / 2 + (start.x - end.x) * (link.curve / 2); diff --git a/app/components/model.ts b/app/components/model.ts index 44fd658d..23e18959 100644 --- a/app/components/model.ts +++ b/app/components/model.ts @@ -52,7 +52,7 @@ const COLORS_ORDER = [ "#80E6E6", ] -export function getCategoryColorValue(index: number): string { +export function getCategoryColorValue(index: number = 0): string { return COLORS_ORDER[index % COLORS_ORDER.length] } @@ -176,13 +176,41 @@ export class Graph { return } - let sourceId = edgeData.src_node; - let destinationId = edgeData.dest_node + let source = this.nodesMap.get(edgeData.src_node) + let target = this.nodesMap.get(edgeData.dest_node) + + if (!source) { + source = { + id: edgeData.src_node, + name: edgeData.src_node, + color: getCategoryColorValue(), + category: "", + expand: false, + visible: true, + collapsed, + isPath: !!path, + isPathSelected: path?.start?.id === edgeData.src_node || path?.end?.id === edgeData.src_node + } + } + + if (!target) { + target = { + id: edgeData.dest_node, + name: edgeData.dest_node, + color: getCategoryColorValue(), + category: "", + expand: false, + visible: true, + collapsed, + isPath: !!path, + isPathSelected: path?.start?.id === edgeData.dest_node || path?.end?.id === edgeData.dest_node + } + } link = { id: edgeData.id, - source: sourceId, - target: destinationId, + source, + target, label: edgeData.relation, visible: true, expand: false, @@ -196,6 +224,34 @@ export class Graph { newElements.links.push(link) }) + newElements.links.forEach(link => { + const start = link.source + const end = link.target + const sameNodesLinks = this.Elements.links.filter(l => (l.source.id === start.id && l.target.id === end.id) || (l.target.id === start.id && l.source.id === end.id)) + const index = sameNodesLinks.findIndex(l => l.id === link.id) || 0 + const even = index % 2 === 0 + let curve + + if (start.id === end.id) { + if (even) { + curve = Math.floor(-(index / 2)) - 3 + } else { + curve = Math.floor((index + 1) / 2) + 2 + } + } else { + console.log(link.curve) + if (even) { + curve = Math.floor(-(index / 2)) + } else { + curve = Math.floor((index + 1) / 2) + } + + } + + link.curve = curve * 0.1 + }) + + return newElements } From 3cf7586f51fa75d3208ecf3354a8d27d43cbc5a9 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Mon, 6 Jan 2025 14:43:58 +0200 Subject: [PATCH 002/189] commit --- tailwind.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tailwind.config.js b/tailwind.config.js index 14d51792..060cc1d9 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -79,6 +79,7 @@ module.exports = { animation: { "accordion-down": "accordion-down 0.2s ease-out", "accordion-up": "accordion-up 0.2s ease-out", + 'spin': 'spin 1s linear', }, }, }, From bde842e8ae84c045672a787ce59a49a6f4d52f66 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Mon, 6 Jan 2025 18:06:11 +0200 Subject: [PATCH 003/189] commit --- app/components/graphView.tsx | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 66d75a2d..f1030806 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -78,18 +78,7 @@ export default function GraphView({ setSelectedObjects([]) } - const handelNodeClick = (node: Node, evt: MouseEvent) => { - if (isShowPath) { - setPath(prev => { - if (!prev?.start?.name || (prev.end?.name && prev.end?.name !== "")) { - return ({ start: { id: Number(node.id), name: node.name } }) - } else { - return ({ end: { id: Number(node.id), name: node.name }, start: prev.start }) - } - }) - return - } - + const handelNodeRightClick = (node: Node, evt: MouseEvent) => { if (evt.ctrlKey) { if (selectedObjects.some(obj => obj.id === node.id)) { setSelectedObjects(selectedObjects.filter(obj => obj.id !== node.id)) @@ -111,8 +100,20 @@ export default function GraphView({ setSelectedPathId(link.id) } - const handelNodeRightClick = async (node: Node) => { + const handelNodeClick = async (node: Node) => { + if (isShowPath) { + setPath(prev => { + if (!prev?.start?.name || (prev.end?.name && prev.end?.name !== "")) { + return ({ start: { id: Number(node.id), name: node.name } }) + } else { + return ({ end: { id: Number(node.id), name: node.name }, start: prev.start }) + } + }) + return + } + const expand = !node.expand + if (expand) { const elements = await onFetchNode([node.id]) @@ -121,6 +122,7 @@ export default function GraphView({ title: `No neighbors found`, description: `No neighbors found`, }) + return } } else { From 6efd86154ee55bc0a5c44e451aaf1d30db8a11a1 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Wed, 8 Jan 2025 13:56:00 +0200 Subject: [PATCH 004/189] expand only on the seconde click --- app/components/graphView.tsx | 54 ++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index f1030806..4eb81d44 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -61,7 +61,7 @@ export default function GraphView({ }: Props) { const parentRef = useRef(null) - + const lastClick = useRef(new Date()) useEffect(() => { setCooldownTime(4000) setCooldownTicks(undefined) @@ -101,7 +101,35 @@ export default function GraphView({ } const handelNodeClick = async (node: Node) => { - if (isShowPath) { + const now = new Date() + + const isDoubleClick = now.getTime() - lastClick.current.getTime() < 1000 + lastClick.current = now + + if (isDoubleClick) { + const expand = !node.expand + + if (expand) { + const elements = await onFetchNode([node.id]) + + if (elements.nodes.length === 0) { + toast({ + title: `No neighbors found`, + description: `No neighbors found`, + }) + + return + } + } else { + deleteNeighbors([node]); + } + + node.expand = expand + + setSelectedObj(undefined) + setData({ ...graph.Elements }) + + } else if (isShowPath) { setPath(prev => { if (!prev?.start?.name || (prev.end?.name && prev.end?.name !== "")) { return ({ start: { id: Number(node.id), name: node.name } }) @@ -111,28 +139,6 @@ export default function GraphView({ }) return } - - const expand = !node.expand - - if (expand) { - const elements = await onFetchNode([node.id]) - - if (elements.nodes.length === 0) { - toast({ - title: `No neighbors found`, - description: `No neighbors found`, - }) - - return - } - } else { - deleteNeighbors([node]); - } - - node.expand = expand - - setSelectedObj(undefined) - setData({ ...graph.Elements }) } return ( From 9e2cf1ffca0e53967046dbec16b3f0c048f3f271 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Wed, 8 Jan 2025 15:23:46 +0200 Subject: [PATCH 005/189] fix zoom on search and in path --- app/components/chat.tsx | 18 ++++++++++++-- app/components/code-graph.tsx | 44 ++++++++++++++++++----------------- app/components/model.ts | 5 ++-- app/page.tsx | 1 + 4 files changed, 43 insertions(+), 25 deletions(-) diff --git a/app/components/chat.tsx b/app/components/chat.tsx index f11f2476..5a861f8f 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -9,6 +9,7 @@ import { cn } from "@/lib/utils"; import { TypeAnimation } from "react-type-animation"; import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; import { prepareArg } from "../utils"; +import { NodeObject } from "react-force-graph-2d"; type PathData = { nodes: any[] @@ -84,6 +85,7 @@ interface Props { isPathResponse: boolean | undefined setIsPathResponse: (isPathResponse: boolean | undefined) => void setData: Dispatch> + chartRef: any } const SUGGESTIONS = [ @@ -105,7 +107,7 @@ const RemoveLastPath = (messages: Message[]) => { return messages } -export function Chat({ repo, path, setPath, graph, selectedPathId, isPathResponse, setIsPathResponse, setData }: Props) { +export function Chat({ repo, path, setPath, graph, selectedPathId, isPathResponse, setIsPathResponse, setData, chartRef }: Props) { // Holds the messages in the chat const [messages, setMessages] = useState([]); @@ -131,7 +133,6 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons const p = paths.find((path) => [...path.links, ...path.nodes].some((e: any) => e.id === selectedPathId)) if (!p) return - handelSetSelectedPath(p) }, [selectedPathId]) @@ -154,6 +155,9 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons }, [isPathResponse]) const handelSetSelectedPath = (p: PathData) => { + const chart = chartRef.current + + if (!chart) return setSelectedPath(prev => { if (prev) { if (isPathResponse && paths.some((path) => [...path.nodes, ...path.links].every((e: any) => [...prev.nodes, ...prev.links].some((e: any) => e.id === e.id)))) { @@ -206,6 +210,9 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons }); } setData({ ...graph.Elements }) + setTimeout(() => { + chart.zoomToFit(1000, 150, (n: NodeObject) => p.nodes.some(node => node.id === n.id)); + }, 0) } // A function that handles the change event of the url input box @@ -262,6 +269,10 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons } const handleSubmit = async () => { + const chart = chartRef.current + + if (!chart) return + setSelectedPath(undefined) if (!path?.start?.id || !path.end?.id) return @@ -297,6 +308,9 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons setPath(undefined) setIsPathResponse(true) setData({ ...graph.Elements }) + setTimeout(() => { + chart.zoomToFit(1000, 150, (n: NodeObject) => formattedPaths.some(p => p.nodes.some(node => node.id === n.id))); + }, 0) } const getTip = (disabled = false) => diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 83d27c88..0704da1f 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -14,6 +14,7 @@ import { Checkbox } from '@/components/ui/checkbox'; import dynamic from 'next/dynamic'; import { Position } from "./graphView"; import { prepareArg } from '../utils'; +import { NodeObject } from "react-force-graph-2d"; const GraphView = dynamic(() => import('./graphView')); @@ -208,34 +209,35 @@ export function CodeGraph({ nodes.forEach((node) => { node.expand = expand }) - + setSelectedObj(undefined) setData({ ...graph.Elements }) } const handelSearchSubmit = (node: any) => { - const n = { name: node.properties.name, id: node.id } - - let chartNode = graph.Elements.nodes.find(n => n.id == node.id) - - if (!chartNode?.visible) { - if (!chartNode) { - chartNode = graph.extend({ nodes: [node], edges: [] }).nodes[0] - } else { - chartNode.visible = true - setCooldownTicks(undefined) - setCooldownTime(1000) - } - graph.visibleLinks(true, [chartNode.id]) - } - - setSearchNode(n) - setData({ ...graph.Elements }) - const chart = chartRef.current - + if (chart) { - chart.centerAt(chartNode.x, chartNode.y, 1000); + const n = { name: node.properties.name, id: node.id } + + let chartNode = graph.Elements.nodes.find(n => n.id == node.id) + + if (!chartNode?.visible) { + if (!chartNode) { + chartNode = graph.extend({ nodes: [node], edges: [] }).nodes[0] + } else { + chartNode.visible = true + setCooldownTicks(undefined) + setCooldownTime(1000) + } + graph.visibleLinks(true, [chartNode!.id]) + setData({ ...graph.Elements }) + } + + setSearchNode(n) + setTimeout(() => { + chart.zoomToFit(1000, 150, (n: NodeObject) => n.id === chartNode!.id); + }, 0) } } diff --git a/app/components/model.ts b/app/components/model.ts index 23e18959..080f7984 100644 --- a/app/components/model.ts +++ b/app/components/model.ts @@ -191,6 +191,7 @@ export class Graph { isPath: !!path, isPathSelected: path?.start?.id === edgeData.src_node || path?.end?.id === edgeData.src_node } + this.nodesMap.set(edgeData.src_node, source) } if (!target) { @@ -205,6 +206,7 @@ export class Graph { isPath: !!path, isPathSelected: path?.start?.id === edgeData.dest_node || path?.end?.id === edgeData.dest_node } + this.nodesMap.set(edgeData.dest_node, target) } link = { @@ -228,7 +230,7 @@ export class Graph { const start = link.source const end = link.target const sameNodesLinks = this.Elements.links.filter(l => (l.source.id === start.id && l.target.id === end.id) || (l.target.id === start.id && l.source.id === end.id)) - const index = sameNodesLinks.findIndex(l => l.id === link.id) || 0 + const index = sameNodesLinks.findIndex(l => l.id === link.id) ?? 0 const even = index % 2 === 0 let curve @@ -239,7 +241,6 @@ export class Graph { curve = Math.floor((index + 1) / 2) + 2 } } else { - console.log(link.curve) if (even) { curve = Math.floor(-(index / 2)) } else { diff --git a/app/page.tsx b/app/page.tsx index a58f1a56..ef7fa374 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -281,6 +281,7 @@ export default function Home() { Date: Sun, 19 Jan 2025 11:39:14 +0200 Subject: [PATCH 006/189] commit --- app/components/chat.tsx | 6 ++--- app/components/code-graph.tsx | 12 +++++----- app/components/elementMenu.tsx | 12 +++++----- app/components/graphView.tsx | 43 ++++++++++++++++++++++++---------- 4 files changed, 45 insertions(+), 28 deletions(-) diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 5a861f8f..6e2c127d 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -133,7 +133,7 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons const p = paths.find((path) => [...path.links, ...path.nodes].some((e: any) => e.id === selectedPathId)) if (!p) return - handelSetSelectedPath(p) + handleSetSelectedPath(p) }, [selectedPathId]) // Scroll to the bottom of the chat on new message @@ -154,7 +154,7 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons setPaths([]) }, [isPathResponse]) - const handelSetSelectedPath = (p: PathData) => { + const handleSetSelectedPath = (p: PathData) => { const chart = chartRef.current if (!chart) return @@ -439,7 +439,7 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons setIsPathResponse(undefined) } - handelSetSelectedPath(p) + handleSetSelectedPath(p) }} >

#{i + 1}

diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 0704da1f..7a99062d 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -82,7 +82,7 @@ export function CodeGraph({ const handleKeyDown = (event: KeyboardEvent) => { if (event.key === 'Delete') { if (selectedObj && selectedObjects.length === 0) return - handelRemove([...selectedObjects.map(obj => obj.id), selectedObj?.id].filter(id => id !== undefined)); + handleRemove([...selectedObjects.map(obj => obj.id), selectedObj?.id].filter(id => id !== undefined)); } }; @@ -214,7 +214,7 @@ export function CodeGraph({ setData({ ...graph.Elements }) } - const handelSearchSubmit = (node: any) => { + const handleSearchSubmit = (node: any) => { const chart = chartRef.current if (chart) { @@ -241,7 +241,7 @@ export function CodeGraph({ } } - const handelRemove = (ids: number[]) => { + const handleRemove = (ids: number[]) => { graph.Elements.nodes.forEach(node => { if (!ids.includes(node.id)) return node.visible = false @@ -274,7 +274,7 @@ export function CodeGraph({ value={searchNode.name} onValueChange={({ name }) => setSearchNode({ name })} icon={} - handleSubmit={handelSearchSubmit} + handleSubmit={handleSearchSubmit} node={searchNode} /> @@ -354,10 +354,10 @@ export function CodeGraph({ setPath(path) setSelectedObj(undefined) }} - handleRemove={handelRemove} + handleRemove={handleRemove} position={position} url={url} - handelExpand={handleExpand} + handleExpand={handleExpand} parentRef={containerRef} /> void; position: Position | undefined; url: string; - handelExpand: (nodes: Node[], expand: boolean) => void; + handleExpand: (nodes: Node[], expand: boolean) => void; parentRef: RefObject; } -export default function ElementMenu({ obj, objects, setPath, handleRemove, position, url, handelExpand, parentRef }: Props) { +export default function ElementMenu({ obj, objects, setPath, handleRemove, position, url, handleExpand, parentRef }: Props) { const [currentObj, setCurrentObj] = useState(); const [containerWidth, setContainerWidth] = useState(0); @@ -68,13 +68,13 @@ export default function ElementMenu({ obj, objects, setPath, handleRemove, posit @@ -114,13 +114,13 @@ export default function ElementMenu({ obj, objects, setPath, handleRemove, posit diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 4eb81d44..33d6f63d 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -1,7 +1,7 @@ import ForceGraph2D from 'react-force-graph-2d'; import { Graph, GraphData, Link, Node } from './model'; -import { Dispatch, RefObject, SetStateAction, useEffect, useRef } from 'react'; +import { Dispatch, RefObject, SetStateAction, useEffect, useRef, useState } from 'react'; import { toast } from '@/components/ui/use-toast'; import { Path } from '../page'; @@ -61,7 +61,23 @@ export default function GraphView({ }: Props) { const parentRef = useRef(null) - const lastClick = useRef(new Date()) + const lastClick = useRef<{ date: Date, name: string }>({ date: new Date(), name: "" }) + const [parentWidth, setParentWidth] = useState(0) + const [parentHeight, setParentHeight] = useState(0) + + useEffect(() => { + if (!chartRef.current || data.nodes.length === 0 || data.links.length === 0) return + chartRef.current.d3Force('link').id((link: any) => link.id).distance(50) + chartRef.current.d3Force('charge').strength(-300) + chartRef.current.d3Force('center').strength(0.05) + }, [chartRef, data.links.length, data.nodes.length]) + + useEffect(() => { + if (!parentRef.current) return + setParentWidth(parentRef.current.clientWidth) + setParentHeight(parentRef.current.clientHeight) + }, [parentRef.current?.clientWidth, parentRef.current?.clientHeight]) + useEffect(() => { setCooldownTime(4000) setCooldownTicks(undefined) @@ -78,7 +94,7 @@ export default function GraphView({ setSelectedObjects([]) } - const handelNodeRightClick = (node: Node, evt: MouseEvent) => { + const handleNodeRightClick = (node: Node, evt: MouseEvent) => { if (evt.ctrlKey) { if (selectedObjects.some(obj => obj.id === node.id)) { setSelectedObjects(selectedObjects.filter(obj => obj.id !== node.id)) @@ -94,18 +110,19 @@ export default function GraphView({ setPosition({ x: evt.clientX, y: evt.clientY }) } - const handelLinkClick = (link: Link, evt: MouseEvent) => { + const handleLinkClick = (link: Link, evt: MouseEvent) => { unsetSelectedObjects(evt) if (!isPathResponse || link.id === selectedPathId) return setSelectedPathId(link.id) } - const handelNodeClick = async (node: Node) => { + const handleNodeClick = async (node: Node) => { const now = new Date() + const { date, name } = lastClick.current + + const isDoubleClick = now.getTime() - date.getTime() < 1000 && name === node.name + lastClick.current = { date: now, name: node.name } - const isDoubleClick = now.getTime() - lastClick.current.getTime() < 1000 - lastClick.current = now - if (isDoubleClick) { const expand = !node.expand @@ -145,8 +162,8 @@ export default function GraphView({
setPosition(prev => { return prev && { x: prev.x + translate.x * chartRef.current.zoom(), y: prev.y + translate.y * chartRef.current.zoom() } })} - onNodeRightClick={handelNodeRightClick} - onLinkClick={handelLinkClick} + onNodeRightClick={handleNodeRightClick} + onLinkClick={handleLinkClick} onBackgroundRightClick={unsetSelectedObjects} onBackgroundClick={unsetSelectedObjects} onZoom={() => unsetSelectedObjects()} From 27b592021a24b130ebb1f9e31d0d33bdd8354fb6 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Sun, 19 Jan 2025 12:16:34 +0200 Subject: [PATCH 007/189] add image capture on canvas --- app/components/code-graph.tsx | 54 ++++++++++++++++++++++++++++++++++- package-lock.json | 45 +++++++++++++++++++++++++++++ package.json | 1 + 3 files changed, 99 insertions(+), 1 deletion(-) diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 7a99062d..e7ff56d6 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -3,7 +3,7 @@ import { GraphData, Node } from "./model"; import { GraphContext } from "./provider"; import { Toolbar } from "./toolbar"; import { Labels } from "./labels"; -import { GitFork, Search, X } from "lucide-react"; +import { Download, GitFork, Search, X } from "lucide-react"; import ElementMenu from "./elementMenu"; import Combobox from "./combobox"; import { toast } from '@/components/ui/use-toast'; @@ -15,6 +15,7 @@ import dynamic from 'next/dynamic'; import { Position } from "./graphView"; import { prepareArg } from '../utils'; import { NodeObject } from "react-force-graph-2d"; +import html2canvas from 'html2canvas'; const GraphView = dynamic(() => import('./graphView')); @@ -252,6 +253,51 @@ export function CodeGraph({ setData({ ...graph.Elements }) } + const handleDownloadImage = async () => { + try { + if (!containerRef.current) { + toast({ + variant: "destructive", + title: "Error", + description: "Graph container not found", + }); + return; + } + + // Wait for any pending renders/animations to complete + await new Promise(resolve => setTimeout(resolve, 500)); + + const canvas = await html2canvas(containerRef.current, { + useCORS: true, + allowTaint: true, + logging: false, + backgroundColor: '#ffffff', + scale: 10, // Increase quality + onclone: (clonedDoc) => { + // Ensure the cloned element maintains proper dimensions + const clonedElement = clonedDoc.querySelector('[data-name="canvas-info-panel"]') as HTMLElement; + if (clonedElement) { + clonedElement.style.position = 'absolute'; + clonedElement.style.bottom = '0'; + } + } + }); + + const dataURL = canvas.toDataURL('image/png'); + const link = document.createElement('a'); + link.href = dataURL; + link.download = `${graphName || 'graph'}.png`; + link.click(); + } catch (error) { + console.error('Error downloading graph image:', error); + toast({ + variant: "destructive", + title: "Error", + description: "Failed to download image. Please try again.", + }); + } + }; + return (
@@ -345,6 +391,12 @@ export function CodeGraph({ className="pointer-events-auto" chartRef={chartRef} /> +
= 0.6.0" + } + }, "node_modules/bezier-js": { "version": "6.1.4", "resolved": "https://registry.npmjs.org/bezier-js/-/bezier-js-6.1.4.tgz", @@ -3642,6 +3651,14 @@ "node": ">= 8" } }, + "node_modules/css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -5238,6 +5255,18 @@ "resolved": "https://registry.npmjs.org/highlightjs-vue/-/highlightjs-vue-1.0.0.tgz", "integrity": "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==" }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -7711,6 +7740,14 @@ "node": ">=6" } }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -7999,6 +8036,14 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index b9cf75f9..e8674026 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "autoprefixer": "^10.4.20", "class-variance-authority": "^0.7.1", "clsx": "^2.1.0", + "html2canvas": "^1.4.1", "lucide-react": "^0.441.0", "next": "^15.1.2", "playwright": "^1.49.1", From 08ef5ec4aa298cdc839adf37b918ae557e9ee8b5 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Sun, 19 Jan 2025 12:19:49 +0200 Subject: [PATCH 008/189] change img to svg --- app/components/code-graph.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index e7ff56d6..53cee0c5 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -283,10 +283,10 @@ export function CodeGraph({ } }); - const dataURL = canvas.toDataURL('image/png'); + const dataURL = canvas.toDataURL('image/svg+xml'); const link = document.createElement('a'); link.href = dataURL; - link.download = `${graphName || 'graph'}.png`; + link.download = `${graphName || 'graph'}.svg`; link.click(); } catch (error) { console.error('Error downloading graph image:', error); From 04c5ab642ce02c2e7051b5a956eb19c3845a7703 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Sun, 19 Jan 2025 17:20:49 +0200 Subject: [PATCH 009/189] commit --- app/components/code-graph.tsx | 38 +++++++++-------------------------- package-lock.json | 6 ++++++ package.json | 1 + 3 files changed, 17 insertions(+), 28 deletions(-) diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 53cee0c5..7fca147d 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -217,12 +217,12 @@ export function CodeGraph({ const handleSearchSubmit = (node: any) => { const chart = chartRef.current - + if (chart) { const n = { name: node.properties.name, id: node.id } let chartNode = graph.Elements.nodes.find(n => n.id == node.id) - + if (!chartNode?.visible) { if (!chartNode) { chartNode = graph.extend({ nodes: [node], edges: [] }).nodes[0] @@ -234,7 +234,7 @@ export function CodeGraph({ graph.visibleLinks(true, [chartNode!.id]) setData({ ...graph.Elements }) } - + setSearchNode(n) setTimeout(() => { chart.zoomToFit(1000, 150, (n: NodeObject) => n.id === chartNode!.id); @@ -255,45 +255,27 @@ export function CodeGraph({ const handleDownloadImage = async () => { try { - if (!containerRef.current) { + const canvas = document.querySelector('.force-graph-container canvas') as HTMLCanvasElement; + if (!canvas) { toast({ - variant: "destructive", title: "Error", - description: "Graph container not found", + description: "Canvas not found", + variant: "destructive", }); return; } - // Wait for any pending renders/animations to complete - await new Promise(resolve => setTimeout(resolve, 500)); - - const canvas = await html2canvas(containerRef.current, { - useCORS: true, - allowTaint: true, - logging: false, - backgroundColor: '#ffffff', - scale: 10, // Increase quality - onclone: (clonedDoc) => { - // Ensure the cloned element maintains proper dimensions - const clonedElement = clonedDoc.querySelector('[data-name="canvas-info-panel"]') as HTMLElement; - if (clonedElement) { - clonedElement.style.position = 'absolute'; - clonedElement.style.bottom = '0'; - } - } - }); - - const dataURL = canvas.toDataURL('image/svg+xml'); + const dataURL = canvas.toDataURL('image/webp'); const link = document.createElement('a'); link.href = dataURL; - link.download = `${graphName || 'graph'}.svg`; + link.download = `${graphName}.webp`; link.click(); } catch (error) { console.error('Error downloading graph image:', error); toast({ - variant: "destructive", title: "Error", description: "Failed to download image. Please try again.", + variant: "destructive", }); } }; diff --git a/package-lock.json b/package-lock.json index 8858b426..f0a0eed2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@radix-ui/react-tooltip": "^1.1.4", "@types/react-gtm-module": "^2.0.4", "autoprefixer": "^10.4.20", + "canvas2svg": "^1.0.16", "class-variance-authority": "^0.7.1", "clsx": "^2.1.0", "html2canvas": "^1.4.1", @@ -3466,6 +3467,11 @@ "node": ">=12" } }, + "node_modules/canvas2svg": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/canvas2svg/-/canvas2svg-1.0.16.tgz", + "integrity": "sha512-r3ryHprzDOtAsFuczw+/DKkLR3XexwIlJWnJ+71I9QF7V9scYaV5JZgYDoCUlYtT3ARnOpDcm/hDNZYbWMRHqA==" + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", diff --git a/package.json b/package.json index e8674026..776bc54d 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "@radix-ui/react-tooltip": "^1.1.4", "@types/react-gtm-module": "^2.0.4", "autoprefixer": "^10.4.20", + "canvas2svg": "^1.0.16", "class-variance-authority": "^0.7.1", "clsx": "^2.1.0", "html2canvas": "^1.4.1", From 39142bbec640665ea27c38e451ae28463faebf01 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Mon, 20 Jan 2025 11:51:39 +0200 Subject: [PATCH 010/189] commit --- app/components/code-graph.tsx | 9 +-- app/components/dataPanel.tsx | 127 ++++++++++++++++++++++----------- app/components/elementMenu.tsx | 81 ++++++++++++--------- app/components/graphView.tsx | 23 ++++-- app/components/model.ts | 2 - package-lock.json | 39 +++++++--- package.json | 1 + 7 files changed, 189 insertions(+), 93 deletions(-) diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 7a99062d..2dc2d44e 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -1,5 +1,5 @@ import { Dispatch, RefObject, SetStateAction, useContext, useEffect, useRef, useState } from "react"; -import { GraphData, Node } from "./model"; +import { GraphData, Link, Node } from "./model"; import { GraphContext } from "./provider"; import { Toolbar } from "./toolbar"; import { Labels } from "./labels"; @@ -21,7 +21,7 @@ const GraphView = dynamic(() => import('./graphView')); interface Props { data: GraphData, setData: Dispatch>, - onFetchGraph: (graphName: string) => void, + onFetchGraph: (graphName: string) => Promise, onFetchNode: (nodeIds: number[]) => Promise, options: string[] setOptions: Dispatch> @@ -55,7 +55,7 @@ export function CodeGraph({ let graph = useContext(GraphContext) const [url, setURL] = useState(""); - const [selectedObj, setSelectedObj] = useState(); + const [selectedObj, setSelectedObj] = useState(); const [selectedObjects, setSelectedObjects] = useState([]); const [position, setPosition] = useState(); const [graphName, setGraphName] = useState(""); @@ -145,9 +145,10 @@ export function CodeGraph({ } run() + }, [graphName]) - function handleSelectedValue(value: string) { + async function handleSelectedValue(value: string) { setGraphName(value) onFetchGraph(value) } diff --git a/app/components/dataPanel.tsx b/app/components/dataPanel.tsx index 07269cd1..21469cb5 100644 --- a/app/components/dataPanel.tsx +++ b/app/components/dataPanel.tsx @@ -1,17 +1,19 @@ -import { Dispatch, SetStateAction, useRef, useEffect, useState } from "react"; -import { Node } from "./model"; +import { Dispatch, SetStateAction } from "react"; +import { JSONTree } from 'react-json-tree'; +import { Link, Node } from "./model"; import { Copy, SquareArrowOutUpRight, X } from "lucide-react"; import SyntaxHighlighter from 'react-syntax-highlighter'; import { dark } from 'react-syntax-highlighter/dist/esm/styles/hljs'; interface Props { - obj: Node | undefined; - setObj: Dispatch>; + obj: Node | Link | undefined; + setObj: Dispatch>; url: string; } const excludedProperties = [ "category", + "label", "color", "expand", "collapsed", @@ -19,7 +21,10 @@ const excludedProperties = [ "isPathStartEnd", "visible", "index", + "curve", "__indexColor", + "isPathSelected", + "__controlPoints", "x", "y", "vx", @@ -30,20 +35,16 @@ const excludedProperties = [ export default function DataPanel({ obj, setObj, url }: Props) { - const containerRef = useRef(null); - const [containerHeight, setContainerHeight] = useState(0); - - useEffect(() => { - if (containerRef.current) { - setContainerHeight(containerRef.current.clientHeight); - } - }, [containerRef.current]); + debugger if (!obj) return null; - const label = `${obj.category}: ${obj.name}` + const type = "category" in obj + const label = type ? `${obj.category}: ${obj.name}` : obj.label const object = Object.entries(obj).filter(([k]) => !excludedProperties.includes(k)) + console.log(obj) + return (
@@ -52,7 +53,7 @@ export default function DataPanel({ obj, setObj, url }: Props) {
-
+
{ object.map(([key, value]) => (
@@ -73,40 +74,86 @@ export default function DataPanel({ obj, setObj, url }: Props) { > {value} - :

{value}

+ : typeof value === "object" ? + !excludedProperties.includes(k)))} + theme={{ + base00: '#343434', // background + base01: '#000000', + base02: '#CE9178', + base03: '#CE9178', // open values + base04: '#CE9178', + base05: '#CE9178', + base06: '#CE9178', + base07: '#CE9178', + base08: '#CE9178', + base09: '#b5cea8', // numbers + base0A: '#CE9178', + base0B: '#CE9178', // close values + base0C: '#CE9178', + base0D: '#99E4E5', // * keys + base0E: '#ae81ff', + base0F: '#cc6633' + }} + valueRenderer={(valueAsString, value, keyPath) => { + if (keyPath === "src") { + return + {value as string} + + } + return {value as string} + }} + /> + : {value} }
)) }
) diff --git a/app/components/elementMenu.tsx b/app/components/elementMenu.tsx index e1451f8a..82775c35 100644 --- a/app/components/elementMenu.tsx +++ b/app/components/elementMenu.tsx @@ -1,14 +1,14 @@ "use client" import { Dispatch, RefObject, SetStateAction, useEffect, useState } from "react"; -import { Node } from "./model"; +import { Link, Node } from "./model"; import { ChevronsLeftRight, Copy, EyeOff, Globe, Maximize2, Minimize2, Waypoints } from "lucide-react"; import DataPanel from "./dataPanel"; import { Path } from "../page"; import { Position } from "./graphView"; interface Props { - obj: Node | undefined; + obj: Node | Link | undefined; objects: Node[]; setPath: Dispatch>; handleRemove: (nodes: number[]) => void; @@ -20,7 +20,7 @@ interface Props { export default function ElementMenu({ obj, objects, setPath, handleRemove, position, url, handleExpand, parentRef }: Props) { - const [currentObj, setCurrentObj] = useState(); + const [currentObj, setCurrentObj] = useState(); const [containerWidth, setContainerWidth] = useState(0); useEffect(() => { @@ -80,13 +80,18 @@ export default function ElementMenu({ obj, objects, setPath, handleRemove, posit : <> - + { + "category" in obj && + <> + + + } - { - window.open(objURL, '_blank'); - }} - > - - + { + "category" in obj && + <> + { + window.open(objURL, '_blank'); + }} + > + + + + } - - + { + "category" in obj && + <> + + + + } } diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 33d6f63d..7a93b1f0 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -15,8 +15,8 @@ interface Props { setData: Dispatch> graph: Graph chartRef: RefObject - selectedObj: Node | undefined - setSelectedObj: Dispatch> + selectedObj: Node | Link | undefined + setSelectedObj: Dispatch> selectedObjects: Node[] setSelectedObjects: Dispatch> setPosition: Dispatch> @@ -65,6 +65,16 @@ export default function GraphView({ const [parentWidth, setParentWidth] = useState(0) const [parentHeight, setParentHeight] = useState(0) + useEffect(() => { + const timeout = setTimeout(() => { + chartRef.current?.zoomToFit(1000, 40) + }, 1000) + + return () => { + clearTimeout(timeout) + } + }, [data.nodes.length, data.links.length, chartRef]) + useEffect(() => { if (!chartRef.current || data.nodes.length === 0 || data.links.length === 0) return chartRef.current.d3Force('link').id((link: any) => link.id).distance(50) @@ -94,13 +104,13 @@ export default function GraphView({ setSelectedObjects([]) } - const handleNodeRightClick = (node: Node, evt: MouseEvent) => { - if (evt.ctrlKey) { + const handleRightClick = (node: Node | Link, evt: MouseEvent) => { + if (evt.ctrlKey && "category" in node) { if (selectedObjects.some(obj => obj.id === node.id)) { setSelectedObjects(selectedObjects.filter(obj => obj.id !== node.id)) return } else { - setSelectedObjects([...selectedObjects, node]) + setSelectedObjects([...selectedObjects, node as Node]) } } else { setSelectedObjects([]) @@ -283,7 +293,8 @@ export default function GraphView({ onNodeDragEnd={(n, translate) => setPosition(prev => { return prev && { x: prev.x + translate.x * chartRef.current.zoom(), y: prev.y + translate.y * chartRef.current.zoom() } })} - onNodeRightClick={handleNodeRightClick} + onNodeRightClick={handleRightClick} + onLinkRightClick={handleRightClick} onLinkClick={handleLinkClick} onBackgroundRightClick={unsetSelectedObjects} onBackgroundClick={unsetSelectedObjects} diff --git a/app/components/model.ts b/app/components/model.ts index 080f7984..d38bc3a2 100644 --- a/app/components/model.ts +++ b/app/components/model.ts @@ -30,8 +30,6 @@ export type Link = LinkObject=0.10.0" } }, + "node_modules/react-base16-styling": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.10.0.tgz", + "integrity": "sha512-H1k2eFB6M45OaiRru3PBXkuCcn2qNmx+gzLb4a9IPMR7tMH8oBRXU5jGbPDYG1Hz+82d88ED0vjR8BmqU3pQdg==", + "dependencies": { + "@types/lodash": "^4.17.0", + "color": "^4.2.3", + "csstype": "^3.1.3", + "lodash-es": "^4.17.21" + } + }, "node_modules/react-dom": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", @@ -6803,6 +6814,19 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "license": "MIT" }, + "node_modules/react-json-tree": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/react-json-tree/-/react-json-tree-0.19.0.tgz", + "integrity": "sha512-PqT1WRVcWP+RROsZPQfNEKIC1iM/ZMfY4g5jN6oDnXp5593PPRAYgoHcgYCDjflAHQMtxl8XGdlTwIBdEGUXvw==", + "dependencies": { + "@types/lodash": "^4.17.0", + "react-base16-styling": "^0.10.0" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-kapsule": { "version": "2.5.6", "resolved": "https://registry.npmjs.org/react-kapsule/-/react-kapsule-2.5.6.tgz", @@ -7328,7 +7352,6 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", - "optional": true, "dependencies": { "is-arrayish": "^0.3.1" } diff --git a/package.json b/package.json index b9cf75f9..638d687b 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "react-dom": "^18", "react-force-graph-2d": "^1.25.8", "react-gtm-module": "^2.0.11", + "react-json-tree": "^0.19.0", "react-resizable-panels": "^2.0.20", "react-syntax-highlighter": "^15.6.1", "react-type-animation": "^3.2.0", From bed88d3f1f7a0a8ca22135cfc0122309f235d671 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Mon, 20 Jan 2025 12:02:20 +0200 Subject: [PATCH 011/189] commit --- app/components/graphView.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 33d6f63d..d76c912e 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -65,13 +65,6 @@ export default function GraphView({ const [parentWidth, setParentWidth] = useState(0) const [parentHeight, setParentHeight] = useState(0) - useEffect(() => { - if (!chartRef.current || data.nodes.length === 0 || data.links.length === 0) return - chartRef.current.d3Force('link').id((link: any) => link.id).distance(50) - chartRef.current.d3Force('charge').strength(-300) - chartRef.current.d3Force('center').strength(0.05) - }, [chartRef, data.links.length, data.nodes.length]) - useEffect(() => { if (!parentRef.current) return setParentWidth(parentRef.current.clientWidth) From 9c8d9cda782cca3ebd419e357e0b767ffda49b9d Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Mon, 20 Jan 2025 12:03:58 +0200 Subject: [PATCH 012/189] commit --- app/components/graphView.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 7a93b1f0..0cf432a9 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -75,13 +75,6 @@ export default function GraphView({ } }, [data.nodes.length, data.links.length, chartRef]) - useEffect(() => { - if (!chartRef.current || data.nodes.length === 0 || data.links.length === 0) return - chartRef.current.d3Force('link').id((link: any) => link.id).distance(50) - chartRef.current.d3Force('charge').strength(-300) - chartRef.current.d3Force('center').strength(0.05) - }, [chartRef, data.links.length, data.nodes.length]) - useEffect(() => { if (!parentRef.current) return setParentWidth(parentRef.current.clientWidth) From d8b94787321d373332fcc36f71e912a977df394f Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Mon, 20 Jan 2025 12:04:25 +0200 Subject: [PATCH 013/189] commit --- app/components/graphView.tsx | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 33d6f63d..5badbd39 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -66,17 +66,14 @@ export default function GraphView({ const [parentHeight, setParentHeight] = useState(0) useEffect(() => { - if (!chartRef.current || data.nodes.length === 0 || data.links.length === 0) return - chartRef.current.d3Force('link').id((link: any) => link.id).distance(50) - chartRef.current.d3Force('charge').strength(-300) - chartRef.current.d3Force('center').strength(0.05) - }, [chartRef, data.links.length, data.nodes.length]) + const timeout = setTimeout(() => { + chartRef.current?.zoomToFit(1000, 40) + }, 1000) - useEffect(() => { - if (!parentRef.current) return - setParentWidth(parentRef.current.clientWidth) - setParentHeight(parentRef.current.clientHeight) - }, [parentRef.current?.clientWidth, parentRef.current?.clientHeight]) + return () => { + clearTimeout(timeout) + } + }, [data.nodes.length, data.links.length, chartRef]) useEffect(() => { setCooldownTime(4000) From 9b46538e13e13bba90202b6f3540670716e89d62 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Mon, 20 Jan 2025 12:05:07 +0200 Subject: [PATCH 014/189] commit --- app/components/graphView.tsx | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 0cf432a9..7150ae17 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -65,16 +65,6 @@ export default function GraphView({ const [parentWidth, setParentWidth] = useState(0) const [parentHeight, setParentHeight] = useState(0) - useEffect(() => { - const timeout = setTimeout(() => { - chartRef.current?.zoomToFit(1000, 40) - }, 1000) - - return () => { - clearTimeout(timeout) - } - }, [data.nodes.length, data.links.length, chartRef]) - useEffect(() => { if (!parentRef.current) return setParentWidth(parentRef.current.clientWidth) From 95518d407d2e0fe65c15a77399c9697b4a779103 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Mon, 20 Jan 2025 12:11:16 +0200 Subject: [PATCH 015/189] commit --- app/components/graphView.tsx | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index d76c912e..f9b8714a 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -66,10 +66,25 @@ export default function GraphView({ const [parentHeight, setParentHeight] = useState(0) useEffect(() => { - if (!parentRef.current) return - setParentWidth(parentRef.current.clientWidth) - setParentHeight(parentRef.current.clientHeight) - }, [parentRef.current?.clientWidth, parentRef.current?.clientHeight]) + const handleResize = () => { + if (!parentRef.current) return + setParentWidth(parentRef.current.clientWidth) + setParentHeight(parentRef.current.clientHeight) + } + + window.addEventListener('resize', handleResize) + + const observer = new ResizeObserver(handleResize) + + if (parentRef.current) { + observer.observe(parentRef.current) + } + + return () => { + window.removeEventListener('resize', handleResize) + observer.disconnect() + } + }, [parentRef]) useEffect(() => { setCooldownTime(4000) From ca2e1f01acacda8e03ddaab7beb5a2ceeeb9ec96 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Mon, 20 Jan 2025 14:17:48 +0200 Subject: [PATCH 016/189] commit --- app/components/code-graph.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 7fca147d..7dddd7af 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -15,7 +15,6 @@ import dynamic from 'next/dynamic'; import { Position } from "./graphView"; import { prepareArg } from '../utils'; import { NodeObject } from "react-force-graph-2d"; -import html2canvas from 'html2canvas'; const GraphView = dynamic(() => import('./graphView')); From 8e5dc72a20fecb7f393ddca2fc299238b361e53a Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Tue, 21 Jan 2025 17:29:32 +0200 Subject: [PATCH 017/189] fix test errors --- e2e/logic/POM/codeGraph.ts | 10 ++++++++-- e2e/tests/canvas.spec.ts | 3 +-- e2e/tests/chat.spec.ts | 5 +++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 9910ded3..5c3afa2c 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -152,6 +152,10 @@ export default class CodeGraph extends BasePage { return this.page.locator("//main[@data-name='main-chat']/*[last()-1]/p"); } + private get responseLoadingImg(): Locator { + return this.page.locator("//img[@alt='Waiting for response']"); + } + /* Canvas Locators*/ private get canvasElement(): Locator { @@ -277,7 +281,8 @@ export default class CodeGraph extends BasePage { } async getTextInLastChatElement(): Promise{ - await delay(2500); + await this.page.waitForSelector('img[alt="Waiting for response"]', { state: 'hidden' }); + await delay(2000); return (await this.lastElementInChat.textContent())!; } @@ -349,6 +354,7 @@ export default class CodeGraph extends BasePage { await this.selectGraphInComboBoxByName(graph).waitFor({ state : 'visible'}) await this.selectGraphInComboBoxByName(graph).click(); } + await delay(2000); // graph animation delay } async createProject(url : string): Promise { @@ -417,7 +423,7 @@ export default class CodeGraph extends BasePage { async nodeClick(x: number, y: number): Promise { await this.canvasElement.hover({ position: { x, y } }); - await this.canvasElement.click({ position: { x, y } }); + await this.canvasElement.click({ position: { x, y }, button: 'right' }); } async selectCodeGraphCheckbox(checkbox: string): Promise { diff --git a/e2e/tests/canvas.spec.ts b/e2e/tests/canvas.spec.ts index 3701ac86..022500e3 100644 --- a/e2e/tests/canvas.spec.ts +++ b/e2e/tests/canvas.spec.ts @@ -43,15 +43,14 @@ test.describe("Canvas tests", () => { test(`Verify center graph button centers nodes in canvas`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); + await codeGraph.clickCenter(); const initialGraph = await codeGraph.getCanvasScaling(); - await codeGraph.clickZoomOut(); await codeGraph.clickZoomOut(); await codeGraph.clickCenter(); const updatedGraph = await codeGraph.getCanvasScaling(); expect(Math.abs(initialGraph.scaleX - updatedGraph.scaleX)).toBeLessThanOrEqual(0.1); expect(Math.abs(initialGraph.scaleY - updatedGraph.scaleY)).toBeLessThanOrEqual(0.1); - }) nodes.slice(0,2).forEach((node) => { diff --git a/e2e/tests/chat.spec.ts b/e2e/tests/chat.spec.ts index 1f245f11..0d1f71cc 100644 --- a/e2e/tests/chat.spec.ts +++ b/e2e/tests/chat.spec.ts @@ -110,12 +110,15 @@ test.describe("Chat tests", () => { const result = await chat.getTextInLastChatElement(); const number = result.match(/\d+/g)?.[0]!; responses.push(number); + } const identicalResponses = responses.every((value) => value === responses[0]); expect(identicalResponses).toBe(true); }); test(`Validate UI response matches API response for a given question in chat`, async () => { + const api = new ApiCalls(); + const apiResponse = await api.askQuestion(PROJECT_NAME, Node_Question); const chat = await browser.createNewPage(CodeGraph, urls.baseUrl); await chat.selectGraph(GRAPH_ID); @@ -123,8 +126,6 @@ test.describe("Chat tests", () => { const uiResponse = await chat.getTextInLastChatElement(); const number = uiResponse.match(/\d+/g)?.[0]!; - const api = new ApiCalls(); - const apiResponse = await api.askQuestion(PROJECT_NAME, Node_Question); expect(number).toEqual(apiResponse.result.response.match(/\d+/g)?.[0]); }); }); From 17d8fd85ca4ef3b600e91b388b68b2d036bfd9d1 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Wed, 22 Jan 2025 10:38:36 +0200 Subject: [PATCH 018/189] Remove 'spin' animation from config --- tailwind.config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tailwind.config.js b/tailwind.config.js index 060cc1d9..14d51792 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -79,7 +79,6 @@ module.exports = { animation: { "accordion-down": "accordion-down 0.2s ease-out", "accordion-up": "accordion-up 0.2s ease-out", - 'spin': 'spin 1s linear', }, }, }, From 1a2a087d8a7fd10ccf68c1f0eddff3b5cf3ca235 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Wed, 22 Jan 2025 16:16:14 +0200 Subject: [PATCH 019/189] Refactor CodeGraph and GraphView components to improve node expansion handling and neighbor deletion logic. Updated deleteNeighbors function to handle expanded nodes correctly and replaced direct calls with handleExpand in GraphView for better clarity and maintainability. --- app/components/code-graph.tsx | 40 ++++++++++++++++++++--------------- app/components/graphView.tsx | 28 +++--------------------- 2 files changed, 26 insertions(+), 42 deletions(-) diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 7a99062d..6297b205 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -166,29 +166,38 @@ export function CodeGraph({ } const deleteNeighbors = (nodes: Node[]) => { + if (nodes.length === 0) return; - + + const expandedNodes: Node[] = [] + graph.Elements = { - nodes: graph.Elements.nodes.map(node => { + nodes: graph.Elements.nodes.filter(node => { + if (!node.collapsed) return true + const isTarget = graph.Elements.links.some(link => link.target.id === node.id && nodes.some(n => n.id === link.source.id)); + + debugger + + if (!isTarget) return true - if (!isTarget || !node.collapsed) return node + const deleted = graph.NodesMap.delete(Number(node.id)) - if (node.expand) { - node.expand = false - deleteNeighbors([node]) + if (deleted && node.expand) { + expandedNodes.push(node) } - graph.NodesMap.delete(Number(node.id)) - }).filter(node => node !== undefined), + return false + }), links: graph.Elements.links } + + deleteNeighbors(expandedNodes) graph.removeLinks() } const handleExpand = async (nodes: Node[], expand: boolean) => { - if (expand) { const elements = await onFetchNode(nodes.map(n => n.id)) @@ -216,12 +225,11 @@ export function CodeGraph({ const handleSearchSubmit = (node: any) => { const chart = chartRef.current - + if (chart) { - const n = { name: node.properties.name, id: node.id } let chartNode = graph.Elements.nodes.find(n => n.id == node.id) - + if (!chartNode?.visible) { if (!chartNode) { chartNode = graph.extend({ nodes: [node], edges: [] }).nodes[0] @@ -233,8 +241,7 @@ export function CodeGraph({ graph.visibleLinks(true, [chartNode!.id]) setData({ ...graph.Elements }) } - - setSearchNode(n) + setTimeout(() => { chart.zoomToFit(1000, 150, (n: NodeObject) => n.id === chartNode!.id); }, 0) @@ -271,8 +278,7 @@ export function CodeGraph({
setSearchNode({ name })} + onValueChange={(node) => setSearchNode(node)} icon={} handleSubmit={handleSearchSubmit} node={searchNode} @@ -371,7 +377,7 @@ export function CodeGraph({ setSelectedObjects={setSelectedObjects} setPosition={setPosition} onFetchNode={onFetchNode} - deleteNeighbors={deleteNeighbors} + handleExpand={handleExpand} isShowPath={isShowPath} setPath={setPath} isPathResponse={isPathResponse} diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index f9b8714a..d40bfcf6 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -2,7 +2,6 @@ import ForceGraph2D from 'react-force-graph-2d'; import { Graph, GraphData, Link, Node } from './model'; import { Dispatch, RefObject, SetStateAction, useEffect, useRef, useState } from 'react'; -import { toast } from '@/components/ui/use-toast'; import { Path } from '../page'; export interface Position { @@ -21,7 +20,7 @@ interface Props { setSelectedObjects: Dispatch> setPosition: Dispatch> onFetchNode: (nodeIds: number[]) => Promise - deleteNeighbors: (nodes: Node[]) => void + handleExpand: (nodes: Node[], expand: boolean) => void isShowPath: boolean setPath: Dispatch> isPathResponse: boolean | undefined @@ -48,7 +47,7 @@ export default function GraphView({ setSelectedObjects, setPosition, onFetchNode, - deleteNeighbors, + handleExpand, isShowPath, setPath, isPathResponse, @@ -132,28 +131,7 @@ export default function GraphView({ lastClick.current = { date: now, name: node.name } if (isDoubleClick) { - const expand = !node.expand - - if (expand) { - const elements = await onFetchNode([node.id]) - - if (elements.nodes.length === 0) { - toast({ - title: `No neighbors found`, - description: `No neighbors found`, - }) - - return - } - } else { - deleteNeighbors([node]); - } - - node.expand = expand - - setSelectedObj(undefined) - setData({ ...graph.Elements }) - + handleExpand([node], !node.expand) } else if (isShowPath) { setPath(prev => { if (!prev?.start?.name || (prev.end?.name && prev.end?.name !== "")) { From 43c94c74e8fa78eddc7735c55180fc048cbeb5a5 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Wed, 22 Jan 2025 16:24:00 +0200 Subject: [PATCH 020/189] fix input --- app/components/Input.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/components/Input.tsx b/app/components/Input.tsx index 83ed01be..9ab6da79 100644 --- a/app/components/Input.tsx +++ b/app/components/Input.tsx @@ -6,7 +6,6 @@ import { cn } from "@/lib/utils" import { prepareArg } from "../utils" interface Props extends React.InputHTMLAttributes { - value?: string graph: Graph onValueChange: (node: PathNode) => void handleSubmit?: (node: any) => void @@ -16,7 +15,7 @@ interface Props extends React.InputHTMLAttributes { scrollToBottom?: () => void } -export default function Input({ value, onValueChange, handleSubmit, graph, icon, node, className, parentClassName, scrollToBottom, ...props }: Props) { +export default function Input({ onValueChange, handleSubmit, graph, icon, node, className, parentClassName, scrollToBottom, ...props }: Props) { const [open, setOpen] = useState(false) const [options, setOptions] = useState([]) @@ -38,15 +37,15 @@ export default function Input({ value, onValueChange, handleSubmit, graph, icon, let isLastRequest = true const timeout = setTimeout(async () => { - if (!value || node?.id) { - if (!value) { + if (!node?.name) { + if (!node?.name) { setOptions([]) } setOpen(false) return } - const result = await fetch(`/api/repo/${prepareArg(graph.Id)}/?prefix=${prepareArg(value)}`, { + const result = await fetch(`/api/repo/${prepareArg(graph.Id)}/?prefix=${prepareArg(node?.name)}`, { method: 'POST' }) @@ -66,7 +65,7 @@ export default function Input({ value, onValueChange, handleSubmit, graph, icon, setOptions(completions || []) - if (completions?.length > 0) { + if (completions?.length > 0 && !node?.id) { setOpen(true) } else { setOpen(false) @@ -77,7 +76,7 @@ export default function Input({ value, onValueChange, handleSubmit, graph, icon, clearTimeout(timeout) isLastRequest = false } - }, [value, graph.Id]) + }, [node?.name, graph.Id]) const handleKeyDown = (e: React.KeyboardEvent) => { const container = containerRef.current @@ -87,6 +86,7 @@ export default function Input({ value, onValueChange, handleSubmit, graph, icon, const option = options.find((o, i) => i === selectedOption) if (!option) return if (handleSubmit) { + onValueChange({ name: option.properties.name, id: option.id }) handleSubmit(option) } else { if (!open) return @@ -144,7 +144,7 @@ export default function Input({ value, onValueChange, handleSubmit, graph, icon, }} onKeyDown={handleKeyDown} className={cn("w-full border p-2 rounded-md pointer-events-auto", className)} - value={value || ""} + value={node?.name || ""} onChange={(e) => { const newVal = e.target.value const invalidChars = /[%*()\-\[\]{};:"|~]/; From 5a97eaf2ad343467d906a6a8ae2201e6eeb967b9 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Thu, 23 Jan 2025 13:51:35 +0200 Subject: [PATCH 021/189] add create repo --- app/api/repo/route.ts | 70 ++++++++++++++-------------- app/components/dataPanel.tsx | 2 +- app/page.tsx | 90 +++++++++++++++++++----------------- 3 files changed, 85 insertions(+), 77 deletions(-) diff --git a/app/api/repo/route.ts b/app/api/repo/route.ts index 95aa6cfb..8fb38dec 100644 --- a/app/api/repo/route.ts +++ b/app/api/repo/route.ts @@ -1,4 +1,4 @@ -import { NextResponse } from "next/server"; +import { NextRequest, NextResponse } from "next/server"; import { getEnvVariables } from "../utils"; export async function GET() { @@ -22,39 +22,41 @@ export async function GET() { return NextResponse.json({ result: repositories }, { status: 200 }) } catch (err) { console.error(err) - return NextResponse.json((err as Error).message, { status: 400 }) + return NextResponse.json((err as Error).message, { status: 400 }) } } -// export async function POST(request: NextRequest) { - -// const repo_url = request.nextUrl.searchParams.get('url'); - -// try { - -// if (!repo_url) { -// throw new Error("URL parameter is missing"); -// } - -// const { url, token } = getEnvVariables(); - -// const result = await fetch(`${url}/process_repo`, { -// method: 'POST', -// body: JSON.stringify({ repo_url, ignore: ["./.github", "./sbin", "./.git", "./deps", "./bin", "./build"] }), -// headers: { -// "Authorization": token, -// 'Content-Type': 'application/json' -// }, -// cache: 'no-store' -// }); - -// if (!result.ok) { -// throw new Error(await result.text()); -// } - -// return NextResponse.json({ message: "success" }, { status: 200 }); -// } catch (err) { -// console.error(err) -// return NextResponse.json((err as Error).message, { status: 400 }); -// } -// } +export async function POST(request: NextRequest) { + + const repo_url = request.nextUrl.searchParams.get('url'); + + try { + + if (!repo_url) { + throw new Error("URL parameter is missing"); + } + + const { url, token } = getEnvVariables(); + + const isLocal = repo_url.startsWith("file://") + + const result = await fetch(`${url}/${isLocal ? "analyze_folder" : "process_repo"}`, { + method: 'POST', + body: JSON.stringify({ repo_url, ignore: ["./.github", "./sbin", "./.git", "./deps", "./bin", "./build"] }), + headers: { + "Authorization": token, + 'Content-Type': 'application/json' + }, + cache: 'no-store' + }); + + if (!result.ok) { + throw new Error(await result.text()); + } + + return NextResponse.json({ message: "success" }, { status: 200 }); + } catch (err) { + console.error(err) + return NextResponse.json((err as Error).message, { status: 400 }); + } +} \ No newline at end of file diff --git a/app/components/dataPanel.tsx b/app/components/dataPanel.tsx index 07269cd1..e87b46a8 100644 --- a/app/components/dataPanel.tsx +++ b/app/components/dataPanel.tsx @@ -16,7 +16,7 @@ const excludedProperties = [ "expand", "collapsed", "isPath", - "isPathStartEnd", + "isPathSelected", "visible", "index", "__indexColor", diff --git a/app/page.tsx b/app/page.tsx index ef7fa374..f6670b3d 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -12,6 +12,8 @@ import { GraphContext } from './components/provider'; import Image from 'next/image'; import { DropdownMenu, DropdownMenuContent, DropdownMenuLabel, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'; import { prepareArg } from './utils'; +import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog'; +import { Progress } from '@/components/ui/progress'; export type PathNode = { id?: number @@ -92,6 +94,7 @@ export default function Home() { title: "Uh oh! Something went wrong.", description: await result.text(), }) + setIsSubmit(false) return } @@ -209,50 +212,53 @@ export default function Home() { } - {/* - - - - - - {!isSubmit ? "CREATE A NEW PROJECT" : "THANK YOU FOR A NEW REQUEST"} - - + { + process.env.NEXT_PUBLIC_LOCAL_MODE && + + + + + + + {!isSubmit ? "CREATE A NEW PROJECT" : "THANK YOU FOR A NEW REQUEST"} + + + { + !isSubmit + ? "Please provide the URL of the project to connect and start querying data" + : "Processing your graph, this could take a while. We appreciate your patience" + } + { - !isSubmit - ? "Please provide the URL of the model to connect and start querying data" - : "Processing your graph, this could take a while. We appreciate your patience" + !isSubmit ? +
+ setCreateURL(e.target.value)} + placeholder="Type Project URL (File:// or https://)" + /> +
+ +
+
+ : } -
- { - !isSubmit ? -
- setCreateURL(e.target.value)} - placeholder="Type URL" - /> -
- -
-
- : - } -
-
*/} + + + }
From ec73ee4a994fde206df8882fe5d74f98f57915fb Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Fri, 24 Jan 2025 08:32:36 +0200 Subject: [PATCH 022/189] add docker-compose --- docker-compose.yml | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..2e4ac22b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,36 @@ +version: "3.9" + +services: + falkordb: + image: falkordb/falkordb:latest + ports: + - "6379:6379" + - "3001:3000" + volumes: + - ./:/data/ + stdin_open: true # Keep the container's STDIN open + tty: true # Allocate a pseudo-TTY + + code-graph-frontend: + image: falkordb/code-graph-frontend:latest + ports: + - "3000:3000" + depends_on: + - code-graph-backend + environment: + - BACKEND_URL=http://code-graph-backend:5000 # Backend service URL + - SECRET_TOKEN=Vespa + + code-graph-backend: + image: falkordb/code-graph-backend:latest + ports: + - "4000:5000" + depends_on: + - falkordb + environment: + - FALKORDB_HOST=falkordb + - FALKORDB_PORT=6379 + - OPENAI_API_KEY=YOUR_OPENAI_API_KEY + - SECRET_TOKEN=Vespa + - FLASK_RUN_HOST=0.0.0.0 + - FLASK_RUN_PORT=5000 From 8f05cf813e1f751f7b6de4ceefd0b03d215561b2 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Wed, 29 Jan 2025 15:44:49 +0200 Subject: [PATCH 023/189] fix tests --- app/components/code-graph.tsx | 2 +- e2e/logic/POM/codeGraph.ts | 3 +- e2e/tests/chat.spec.ts | 62 +++++++++++++++++------------------ 3 files changed, 34 insertions(+), 33 deletions(-) diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 7a99062d..a47cb798 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -271,7 +271,7 @@ export function CodeGraph({
setSearchNode({ name })} icon={} handleSubmit={handleSearchSubmit} diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 5c3afa2c..bde0a3c8 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -271,6 +271,7 @@ export default class CodeGraph extends BasePage { } async sendMessage(message: string) { + await delay(3000); //delay before sending a request to the AI model await waitToBeEnabled(this.askquestionInput); await this.askquestionInput.fill(message); await this.askquestionBtn.click(); @@ -282,7 +283,7 @@ export default class CodeGraph extends BasePage { async getTextInLastChatElement(): Promise{ await this.page.waitForSelector('img[alt="Waiting for response"]', { state: 'hidden' }); - await delay(2000); + await delay(2000); //delay for chat response animation return (await this.lastElementInChat.textContent())!; } diff --git a/e2e/tests/chat.spec.ts b/e2e/tests/chat.spec.ts index 0d1f71cc..1ec2edab 100644 --- a/e2e/tests/chat.spec.ts +++ b/e2e/tests/chat.spec.ts @@ -31,7 +31,7 @@ test.describe("Chat tests", () => { await chat.selectGraph(GRAPH_ID); const isLoadingArray: boolean[] = []; - for (let i = 0; i < 5; i++) { + for (let i = 0; i < 3; i++) { await chat.sendMessage(Node_Question); const isLoading: boolean = await chat.getpreviousQuestionLoadingImage(); isLoadingArray.push(isLoading); @@ -45,18 +45,46 @@ test.describe("Chat tests", () => { test("Verify auto-scroll and manual scroll in chat", async () => { const chat = await browser.createNewPage(CodeGraph, urls.baseUrl); await chat.selectGraph(GRAPH_ID); - for (let i = 0; i < 5; i++) { + for (let i = 0; i < 3; i++) { await chat.sendMessage(Node_Question); } await delay(500); await chat.scrollToTop(); const { scrollTop } = await chat.getScrollMetrics(); expect(scrollTop).toBeLessThanOrEqual(1); - await chat.sendMessage("Latest Message"); + await chat.sendMessage(Node_Question); await delay(500); expect(await chat.isAtBottom()).toBe(true); }); + test(`Validate consistent UI responses for repeated questions in chat`, async () => { + const chat = await browser.createNewPage(CodeGraph, urls.baseUrl); + await chat.selectGraph(GRAPH_ID); + const responses: string[] = []; + for (let i = 0; i < 3; i++) { + await chat.sendMessage(Node_Question); + const result = await chat.getTextInLastChatElement(); + const number = result.match(/\d+/g)?.[0]!; + responses.push(number); + + } + const identicalResponses = responses.every((value) => value === responses[0]); + expect(identicalResponses).toBe(true); + }); + + test(`Validate UI response matches API response for a given question in chat`, async () => { + const api = new ApiCalls(); + const apiResponse = await api.askQuestion(PROJECT_NAME, Node_Question); + const chat = await browser.createNewPage(CodeGraph, urls.baseUrl); + await chat.selectGraph(GRAPH_ID); + + await chat.sendMessage(Node_Question); + const uiResponse = await chat.getTextInLastChatElement(); + const number = uiResponse.match(/\d+/g)?.[0]!; + + expect(number).toEqual(apiResponse.result.response.match(/\d+/g)?.[0]); + }); + nodesPath.forEach((path) => { test(`Verify successful node path connection between two nodes in chat for ${path.firstNode} and ${path.secondNode}`, async () => { const chat = await browser.createNewPage(CodeGraph, urls.baseUrl); @@ -100,32 +128,4 @@ test.describe("Chat tests", () => { expect(selectedQuestion).toEqual(await chat.getLastQuestionInChat()) }); } - - test(`Validate consistent UI responses for repeated questions in chat`, async () => { - const chat = await browser.createNewPage(CodeGraph, urls.baseUrl); - await chat.selectGraph(GRAPH_ID); - const responses: string[] = []; - for (let i = 0; i < 3; i++) { - await chat.sendMessage(Node_Question); - const result = await chat.getTextInLastChatElement(); - const number = result.match(/\d+/g)?.[0]!; - responses.push(number); - - } - const identicalResponses = responses.every((value) => value === responses[0]); - expect(identicalResponses).toBe(true); - }); - - test(`Validate UI response matches API response for a given question in chat`, async () => { - const api = new ApiCalls(); - const apiResponse = await api.askQuestion(PROJECT_NAME, Node_Question); - const chat = await browser.createNewPage(CodeGraph, urls.baseUrl); - await chat.selectGraph(GRAPH_ID); - - await chat.sendMessage(Node_Question); - const uiResponse = await chat.getTextInLastChatElement(); - const number = uiResponse.match(/\d+/g)?.[0]!; - - expect(number).toEqual(apiResponse.result.response.match(/\d+/g)?.[0]); - }); }); From a7c282d5e196ff3d152140ec4b95912d5ec794a5 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Wed, 29 Jan 2025 17:14:04 +0200 Subject: [PATCH 024/189] fix chat error & increase timing --- app/components/chat.tsx | 4 ++-- e2e/logic/POM/codeGraph.ts | 6 ++++-- e2e/tests/chat.spec.ts | 10 ++++++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 6e2c127d..6af9ac79 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -387,7 +387,7 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons parentClassName="w-full" graph={graph} onValueChange={({ name, id }) => setPath(prev => ({ start: { name, id }, end: prev?.end }))} - value={path?.start?.name} + value={path?.start?.name || ""} placeholder="Start typing starting point" type="text" icon={} @@ -397,7 +397,7 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons setPath(prev => ({ end: { name, id }, start: prev?.start }))} placeholder="Start typing end point" type="text" diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index bde0a3c8..49a40d68 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -271,7 +271,6 @@ export default class CodeGraph extends BasePage { } async sendMessage(message: string) { - await delay(3000); //delay before sending a request to the AI model await waitToBeEnabled(this.askquestionInput); await this.askquestionInput.fill(message); await this.askquestionBtn.click(); @@ -280,9 +279,12 @@ export default class CodeGraph extends BasePage { async clickOnLightBulbBtn(): Promise { await this.lightbulbBtn.click(); } + private get waitingForResponseIndicator(): Locator { + return this.page.locator('img[alt="Waiting for response"]'); + } async getTextInLastChatElement(): Promise{ - await this.page.waitForSelector('img[alt="Waiting for response"]', { state: 'hidden' }); + await this.waitingForResponseIndicator.waitFor({ state: 'hidden' }); await delay(2000); //delay for chat response animation return (await this.lastElementInChat.textContent())!; } diff --git a/e2e/tests/chat.spec.ts b/e2e/tests/chat.spec.ts index 1ec2edab..5d908bc8 100644 --- a/e2e/tests/chat.spec.ts +++ b/e2e/tests/chat.spec.ts @@ -39,6 +39,7 @@ test.describe("Chat tests", () => { const prevIsLoading = isLoadingArray[i - 1]; expect(prevIsLoading).toBe(false); } + await delay(3000); } }); @@ -47,13 +48,14 @@ test.describe("Chat tests", () => { await chat.selectGraph(GRAPH_ID); for (let i = 0; i < 3; i++) { await chat.sendMessage(Node_Question); + await delay(3000); } - await delay(500); + await delay(500); // delay for scroll await chat.scrollToTop(); const { scrollTop } = await chat.getScrollMetrics(); expect(scrollTop).toBeLessThanOrEqual(1); await chat.sendMessage(Node_Question); - await delay(500); + await delay(500); // delay for scroll expect(await chat.isAtBottom()).toBe(true); }); @@ -66,7 +68,7 @@ test.describe("Chat tests", () => { const result = await chat.getTextInLastChatElement(); const number = result.match(/\d+/g)?.[0]!; responses.push(number); - + await delay(3000); //delay before asking next question } const identicalResponses = responses.every((value) => value === responses[0]); expect(identicalResponses).toBe(true); @@ -77,7 +79,7 @@ test.describe("Chat tests", () => { const apiResponse = await api.askQuestion(PROJECT_NAME, Node_Question); const chat = await browser.createNewPage(CodeGraph, urls.baseUrl); await chat.selectGraph(GRAPH_ID); - + await delay(3000); await chat.sendMessage(Node_Question); const uiResponse = await chat.getTextInLastChatElement(); const number = uiResponse.match(/\d+/g)?.[0]!; From 7b9acf627775fe8e28daa6ed3de8023e1b892113 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Wed, 29 Jan 2025 21:16:36 +0200 Subject: [PATCH 025/189] improve tests timing and locators --- e2e/logic/POM/codeGraph.ts | 49 +++++++++++++++++++++++--------------- e2e/logic/utils.ts | 34 ++++++++++++++++++++------ e2e/tests/chat.spec.ts | 2 ++ 3 files changed, 59 insertions(+), 26 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 49a40d68..4dfc6943 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -1,6 +1,6 @@ import { Locator, Page } from "playwright"; import BasePage from "../../infra/ui/basePage"; -import { delay, waitToBeEnabled } from "../utils"; +import { waitForStableText, waitToBeEnabled } from "../utils"; declare global { interface Window { @@ -253,7 +253,7 @@ export default class CodeGraph extends BasePage { } async isTipMenuVisible(): Promise { - await delay(500); + await this.page.waitForTimeout(500); return await this.genericMenu.isVisible(); } @@ -267,11 +267,12 @@ export default class CodeGraph extends BasePage { } async clickAskquestionBtn(): Promise { + await waitToBeEnabled(this.askquestionBtn); await this.askquestionBtn.click(); } async sendMessage(message: string) { - await waitToBeEnabled(this.askquestionInput); + await waitToBeEnabled(this.askquestionBtn); await this.askquestionInput.fill(message); await this.askquestionBtn.click(); } @@ -285,8 +286,7 @@ export default class CodeGraph extends BasePage { async getTextInLastChatElement(): Promise{ await this.waitingForResponseIndicator.waitFor({ state: 'hidden' }); - await delay(2000); //delay for chat response animation - return (await this.lastElementInChat.textContent())!; + return await waitForStableText(this.lastElementInChat); } async getLastChatElementButtonCount(): Promise{ @@ -326,7 +326,7 @@ export default class CodeGraph extends BasePage { } async isNotificationError(): Promise { - await delay(500); + await this.page.waitForTimeout(500); return await this.notificationError.isVisible(); } @@ -357,7 +357,7 @@ export default class CodeGraph extends BasePage { await this.selectGraphInComboBoxByName(graph).waitFor({ state : 'visible'}) await this.selectGraphInComboBoxByName(graph).click(); } - await delay(2000); // graph animation delay + await this.page.waitForTimeout(2000); // graph animation delay } async createProject(url : string): Promise { @@ -386,8 +386,9 @@ export default class CodeGraph extends BasePage { } async selectSearchBarOptionBtn(buttonNum: string): Promise { - await delay(1000); - await this.searchBarOptionBtn(buttonNum).click(); + const button = this.searchBarOptionBtn(buttonNum); + await button.waitFor({ state : "visible"}) + await button.click(); } async getSearchBarInputValue(): Promise { @@ -417,11 +418,13 @@ export default class CodeGraph extends BasePage { async clickCenter(): Promise { await this.centerBtn.click(); - await delay(2000); //animation delay + await this.page.waitForTimeout(2000); //animation delay } async clickOnRemoveNodeViaElementMenu(): Promise { - await this.elementMenuButton("Remove").click(); + const button = this.elementMenuButton("Remove"); + await button.waitFor({ state: "visible"}) + await button.click(); } async nodeClick(x: number, y: number): Promise { @@ -456,15 +459,21 @@ export default class CodeGraph extends BasePage { } async isNodeDetailsPanel(): Promise { + await this.page.waitForTimeout(500); return this.nodeDetailsPanel.isVisible(); } async clickOnViewNode(): Promise { - await this.elementMenuButton("View Node").click(); + const button = this.elementMenuButton("View Node"); + await button.waitFor({ state: "visible"}) + await button.click(); } async getNodeDetailsHeader(): Promise { - await this.elementMenuButton("View Node").click(); + const button = this.elementMenuButton("View Node"); + await button.waitFor({ state: "visible"}) + await button.click(); + await this.nodedetailsPanelHeader.waitFor({ state: "visible" }) const text = await this.nodedetailsPanelHeader.innerHTML(); return text; } @@ -480,14 +489,15 @@ export default class CodeGraph extends BasePage { } async clickOnCopyToClipboardNodePanelDetails(): Promise { + await this.copyToClipboardNodePanelDetails.waitFor({ state: "visible" }); await this.copyToClipboardNodePanelDetails.click(); - await delay(1000) return await this.page.evaluate(() => navigator.clipboard.readText()); } async clickOnCopyToClipboard(): Promise { - await this.elementMenuButton("Copy src to clipboard").click(); - await delay(1000) + const button = this.elementMenuButton("Copy src to clipboard"); + await button.waitFor({ state: "visible" }); + await button.click(); return await this.page.evaluate(() => navigator.clipboard.readText()); } @@ -496,15 +506,16 @@ export default class CodeGraph extends BasePage { } async getNodeDetailsPanelElements(): Promise { - await this.elementMenuButton("View Node").click(); - await delay(500) + const button = this.elementMenuButton("View Node"); + await button.waitFor({ state: "visible"}) + await button.click(); const elements = await this.nodedetailsPanelElements.all(); return Promise.all(elements.map(element => element.innerHTML())); } async getGraphDetails(): Promise { await this.canvasElementBeforeGraphSelection.waitFor({ state: 'detached' }); - await delay(2000) + await this.page.waitForTimeout(2000); //canvas animation await this.page.waitForFunction(() => !!window.graph); const graphData = await this.page.evaluate(() => { diff --git a/e2e/logic/utils.ts b/e2e/logic/utils.ts index 6ba3475d..efa4adb8 100644 --- a/e2e/logic/utils.ts +++ b/e2e/logic/utils.ts @@ -2,19 +2,39 @@ import { Locator } from "@playwright/test"; export const delay = (ms: number): Promise => new Promise(resolve => setTimeout(resolve, ms)); -export const waitToBeEnabled = async (locator: Locator, timeout: number = 5000): Promise => { - const startTime = Date.now(); +export const waitToBeEnabled = async (locator: Locator, timeout: number = 5000): Promise => { + const elementHandle = await locator.elementHandle(); + if (!elementHandle) throw new Error("Element not found"); - while (Date.now() - startTime < timeout) { - if (await locator.isEnabled()) { - return true; + await locator.page().waitForFunction( + (el) => el && !(el as HTMLElement).hasAttribute("disabled"), + elementHandle, + { timeout } + ); +}; + +export const waitForStableText = async (locator: Locator, timeout: number = 5000): Promise => { + const elementHandle = await locator.elementHandle(); + if (!elementHandle) throw new Error("Element not found"); + + let previousText = ""; + let stableText = ""; + const pollingInterval = 300; + const maxChecks = timeout / pollingInterval; + + for (let i = 0; i < maxChecks; i++) { + stableText = await locator.textContent() ?? ""; + if (stableText === previousText && stableText.trim().length > 0) { + return stableText; } - await new Promise(resolve => setTimeout(resolve, 100)); + previousText = stableText; + await locator.page().waitForTimeout(pollingInterval); } - return false; + return stableText; }; + export function findNodeByName(nodes: { name: string }[], nodeName: string): any { return nodes.find((node) => node.name === nodeName); } \ No newline at end of file diff --git a/e2e/tests/chat.spec.ts b/e2e/tests/chat.spec.ts index 5d908bc8..4bce6f0a 100644 --- a/e2e/tests/chat.spec.ts +++ b/e2e/tests/chat.spec.ts @@ -128,6 +128,8 @@ test.describe("Chat tests", () => { await chat.clickOnQuestionOptionsMenu(); const selectedQuestion = await chat.selectAndGetQuestionInOptionsMenu(questionNumber.toString()); expect(selectedQuestion).toEqual(await chat.getLastQuestionInChat()) + const result = await chat.getTextInLastChatElement(); + expect(result).toBeDefined(); }); } }); From e6972d494e34283767780c060c1d1c6ebe62c622 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Wed, 29 Jan 2025 21:58:49 +0200 Subject: [PATCH 026/189] update locators --- app/components/elementMenu.tsx | 1 + e2e/logic/POM/codeGraph.ts | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/components/elementMenu.tsx b/app/components/elementMenu.tsx index e1451f8a..b205ec0d 100644 --- a/app/components/elementMenu.tsx +++ b/app/components/elementMenu.tsx @@ -45,6 +45,7 @@ export default function ElementMenu({ obj, objects, setPath, handleRemove, posit left: Math.max(-34, Math.min(position.x - 33 - containerWidth / 2, (parentRef?.current?.clientWidth || 0) + 32 - containerWidth)), top: Math.min(position.y - 153, (parentRef?.current?.clientHeight || 0) - 9), }} + id="elementMenu" > { objects.some(o => o.id === obj.id) && objects.length > 1 ? diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 4dfc6943..426d29ab 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -193,6 +193,10 @@ export default class CodeGraph extends BasePage { private get nodeDetailsPanel(): Locator { return this.page.locator("//div[@data-name='node-details-panel']"); } + + private get elementMenu(): Locator { + return this.page.locator("//div[@id='elementMenu']"); + } private get nodedetailsPanelHeader(): Locator { return this.page.locator("//div[@data-name='node-details-panel']/header/p"); @@ -422,8 +426,8 @@ export default class CodeGraph extends BasePage { } async clickOnRemoveNodeViaElementMenu(): Promise { + await this.elementMenu.waitFor({ state: "visible", timeout: 10000}) const button = this.elementMenuButton("Remove"); - await button.waitFor({ state: "visible"}) await button.click(); } @@ -470,10 +474,10 @@ export default class CodeGraph extends BasePage { } async getNodeDetailsHeader(): Promise { + await this.elementMenu.waitFor({ state: "visible", timeout: 10000}) const button = this.elementMenuButton("View Node"); - await button.waitFor({ state: "visible"}) await button.click(); - await this.nodedetailsPanelHeader.waitFor({ state: "visible" }) + await this.nodedetailsPanelHeader.waitFor({ state: "visible", timeout: 10000 }) const text = await this.nodedetailsPanelHeader.innerHTML(); return text; } From fb07797d9fb4f9bc2f67135092d19385e6db8795 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Thu, 30 Jan 2025 13:32:49 +0200 Subject: [PATCH 027/189] replace test size to 2px --- app/components/graphView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index f9b8714a..8651eafd 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -230,7 +230,7 @@ export default function GraphView({ ctx.fillStyle = 'black'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; - ctx.font = '4px Arial'; + ctx.font = '2px Arial'; const textWidth = ctx.measureText(node.name).width; const ellipsis = '...'; const ellipsisWidth = ctx.measureText(ellipsis).width; From e2f506e97952cb0448f15bbc5d3635c68b689ff5 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Thu, 30 Jan 2025 16:35:23 +0200 Subject: [PATCH 028/189] add logging --- e2e/logic/POM/codeGraph.ts | 5 +++++ e2e/tests/nodeDetailsPanel.spec.ts | 1 + 2 files changed, 6 insertions(+) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 426d29ab..02ee94a0 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -432,8 +432,13 @@ export default class CodeGraph extends BasePage { } async nodeClick(x: number, y: number): Promise { + await this.page.waitForTimeout(500); + console.log(`Clicking node at: X=${x}, Y=${y}`); await this.canvasElement.hover({ position: { x, y } }); + await this.page.waitForTimeout(300); // Allow hover to take effect + console.log("Hover successful"); await this.canvasElement.click({ position: { x, y }, button: 'right' }); + console.log("Right-click performed"); } async selectCodeGraphCheckbox(checkbox: string): Promise { diff --git a/e2e/tests/nodeDetailsPanel.spec.ts b/e2e/tests/nodeDetailsPanel.spec.ts index aa59a6fe..5f69afd4 100644 --- a/e2e/tests/nodeDetailsPanel.spec.ts +++ b/e2e/tests/nodeDetailsPanel.spec.ts @@ -25,6 +25,7 @@ test.describe("Node details panel tests", () => { const graphData = await codeGraph.getGraphDetails(); const convertCoordinates = await codeGraph.transformNodeCoordinates(graphData); const targetNode = findNodeByName(convertCoordinates, node.nodeName); + expect(targetNode).toBeDefined(); await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); await codeGraph.clickOnViewNode(); expect(await codeGraph.isNodeDetailsPanel()).toBe(true) From aaedf000c066e755cc7e391c39772e57b4c8a7fc Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Fri, 31 Jan 2025 18:40:43 +0200 Subject: [PATCH 029/189] tests improvements --- e2e/logic/POM/codeGraph.ts | 127 ++++++++++++++++++++++++------------- e2e/logic/utils.ts | 11 ++++ e2e/tests/canvas.spec.ts | 6 +- e2e/tests/chat.spec.ts | 6 +- 4 files changed, 100 insertions(+), 50 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 02ee94a0..4ee1a0b4 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -1,6 +1,6 @@ import { Locator, Page } from "playwright"; import BasePage from "../../infra/ui/basePage"; -import { waitForStableText, waitToBeEnabled } from "../utils"; +import { waitForElementToBeVisible, waitForStableText, waitToBeEnabled } from "../utils"; declare global { interface Window { @@ -156,6 +156,10 @@ export default class CodeGraph extends BasePage { return this.page.locator("//img[@alt='Waiting for response']"); } + private get waitingForResponseIndicator(): Locator { + return this.page.locator('img[alt="Waiting for response"]'); + } + /* Canvas Locators*/ private get canvasElement(): Locator { @@ -245,69 +249,83 @@ export default class CodeGraph extends BasePage { } async clickCreateNewProjectBtn(): Promise { + const isVisible = await waitForElementToBeVisible(this.createNewProjectBtn); + if (!isVisible) throw new Error("'Create New Project' button is not visible!"); await this.createNewProjectBtn.click(); } - + async isCreateNewProjectDialog(): Promise { - return await this.createNewProjectDialog.isVisible(); + return await waitForElementToBeVisible(this.createNewProjectDialog); } - - async clickonTipBtn(): Promise { + + async clickOnTipBtn(): Promise { + const isVisible = await waitForElementToBeVisible(this.tipBtn); + if (!isVisible) throw new Error("'Tip' button is not visible!"); await this.tipBtn.click(); } async isTipMenuVisible(): Promise { - await this.page.waitForTimeout(500); - return await this.genericMenu.isVisible(); + // await this.page.waitForTimeout(500); + return await waitForElementToBeVisible(this.genericMenu); } - - async clickonTipMenuCloseBtn(): Promise { + + async clickOnTipMenuCloseBtn(): Promise { + const isVisible = await waitForElementToBeVisible(this.tipMenuCloseBtn); + if (!isVisible) throw new Error("'Tip Menu Close' button is not visible!"); await this.tipMenuCloseBtn.click(); } + /* Chat functionality */ - async clickOnshowPathBtn(): Promise { + async clickOnShowPathBtn(): Promise { await this.showPathBtn.click(); } - async clickAskquestionBtn(): Promise { - await waitToBeEnabled(this.askquestionBtn); + async clickAskQuestionBtn(): Promise { + const isVisible = await waitForElementToBeVisible(this.askquestionBtn); + if (!isVisible) throw new Error("'Ask Question' button is not visible!"); await this.askquestionBtn.click(); } - + async sendMessage(message: string) { await waitToBeEnabled(this.askquestionBtn); await this.askquestionInput.fill(message); await this.askquestionBtn.click(); } - + async clickOnLightBulbBtn(): Promise { await this.lightbulbBtn.click(); } - private get waitingForResponseIndicator(): Locator { - return this.page.locator('img[alt="Waiting for response"]'); - } async getTextInLastChatElement(): Promise{ await this.waitingForResponseIndicator.waitFor({ state: 'hidden' }); return await waitForStableText(this.lastElementInChat); } - async getLastChatElementButtonCount(): Promise{ + async getLastChatElementButtonCount(): Promise { + const isVisible = await waitForElementToBeVisible(this.lastChatElementButtonCount); + if (!isVisible) return null; return await this.lastChatElementButtonCount.count(); } - async scrollToTop() { + async scrollToTop(): Promise { + const isVisible = await waitForElementToBeVisible(this.chatContainer); + if (!isVisible) throw new Error("Chat container is not visible!"); + await this.chatContainer.evaluate((chat) => { - chat.scrollTop = 0; + chat.scrollTop = 0; }); } async getScrollMetrics() { - const scrollTop = await this.chatContainer.evaluate((el) => el.scrollTop); - const scrollHeight = await this.chatContainer.evaluate((el) => el.scrollHeight); - const clientHeight = await this.chatContainer.evaluate((el) => el.clientHeight); - return { scrollTop, scrollHeight, clientHeight }; + const isVisible = await waitForElementToBeVisible(this.chatContainer); + if (!isVisible) throw new Error("Chat container is not visible!"); + + return await this.chatContainer.evaluate((el) => ({ + scrollTop: el.scrollTop, + scrollHeight: el.scrollHeight, + clientHeight: el.clientHeight + })); } async isAtBottom(): Promise { @@ -323,10 +341,10 @@ export default class CodeGraph extends BasePage { await this.selectInputForShowPath(inputNum).fill(node); await this.selectFirstPathOption(inputNum).click(); } - + async isNodeVisibleInLastChatPath(node: string): Promise { - await this.locateNodeInLastChatPath(node).waitFor({ state: 'visible' }); - return await this.locateNodeInLastChatPath(node).isVisible(); + const nodeLocator = this.locateNodeInLastChatPath(node); + return await waitForElementToBeVisible(nodeLocator); } async isNotificationError(): Promise { @@ -335,21 +353,31 @@ export default class CodeGraph extends BasePage { } async clickOnNotificationErrorCloseBtn(): Promise { + const isVisible = await waitForElementToBeVisible(this.notificationErrorCloseBtn); + if (!isVisible) throw new Error("Notification error close button is not visible!"); await this.notificationErrorCloseBtn.click(); } - + async clickOnQuestionOptionsMenu(): Promise { + const isVisible = await waitForElementToBeVisible(this.questionOptionsMenu); + if (!isVisible) throw new Error("Question options menu is not visible!"); await this.questionOptionsMenu.click(); } - + async selectAndGetQuestionInOptionsMenu(questionNumber: string): Promise { - await this.selectQuestionInMenu(questionNumber).click(); - return await this.selectQuestionInMenu(questionNumber).innerHTML(); + const question = this.selectQuestionInMenu(questionNumber); + const isVisible = await waitForElementToBeVisible(question); + if (!isVisible) throw new Error(`Question ${questionNumber} in menu is not visible!`); + + await question.click(); + return await question.innerHTML(); } - + async getLastQuestionInChat(): Promise { + const isVisible = await waitForElementToBeVisible(this.lastQuestionInChat); + if (!isVisible) throw new Error("Last question in chat is not visible!"); return await this.lastQuestionInChat.innerText(); - } + } /* CodeGraph functionality */ async selectGraph(graph: string | number): Promise { @@ -435,7 +463,7 @@ export default class CodeGraph extends BasePage { await this.page.waitForTimeout(500); console.log(`Clicking node at: X=${x}, Y=${y}`); await this.canvasElement.hover({ position: { x, y } }); - await this.page.waitForTimeout(300); // Allow hover to take effect + await this.page.waitForTimeout(500); // Allow hover to take effect console.log("Hover successful"); await this.canvasElement.click({ position: { x, y }, button: 'right' }); console.log("Right-click performed"); @@ -474,17 +502,21 @@ export default class CodeGraph extends BasePage { async clickOnViewNode(): Promise { const button = this.elementMenuButton("View Node"); - await button.waitFor({ state: "visible"}) + const isButtonVisible = await waitForElementToBeVisible(button); + if (!isButtonVisible) throw new Error("'View Node' button is not visible!"); await button.click(); } async getNodeDetailsHeader(): Promise { - await this.elementMenu.waitFor({ state: "visible", timeout: 10000}) - const button = this.elementMenuButton("View Node"); - await button.click(); - await this.nodedetailsPanelHeader.waitFor({ state: "visible", timeout: 10000 }) - const text = await this.nodedetailsPanelHeader.innerHTML(); - return text; + const isMenuVisible = await waitForElementToBeVisible(this.elementMenu); + if (!isMenuVisible) throw new Error("Element menu did not appear!"); + + await this.clickOnViewNode(); + + const isHeaderVisible = await waitForElementToBeVisible(this.nodedetailsPanelHeader); + if (!isHeaderVisible) throw new Error("Node details panel header did not appear!"); + + return this.nodedetailsPanelHeader.innerHTML(); } async clickOnNodeDetailsCloseBtn(): Promise{ @@ -498,14 +530,16 @@ export default class CodeGraph extends BasePage { } async clickOnCopyToClipboardNodePanelDetails(): Promise { - await this.copyToClipboardNodePanelDetails.waitFor({ state: "visible" }); + const isButtonVisible = await waitForElementToBeVisible(this.copyToClipboardNodePanelDetails); + if (!isButtonVisible) throw new Error("'copy to clipboard button is not visible!"); await this.copyToClipboardNodePanelDetails.click(); return await this.page.evaluate(() => navigator.clipboard.readText()); } async clickOnCopyToClipboard(): Promise { const button = this.elementMenuButton("Copy src to clipboard"); - await button.waitFor({ state: "visible" }); + const isVisible = await waitForElementToBeVisible(button); + if (!isVisible) throw new Error("View Node button is not visible!"); await button.click(); return await this.page.evaluate(() => navigator.clipboard.readText()); } @@ -516,8 +550,13 @@ export default class CodeGraph extends BasePage { async getNodeDetailsPanelElements(): Promise { const button = this.elementMenuButton("View Node"); - await button.waitFor({ state: "visible"}) + const isVisible = await waitForElementToBeVisible(button); + if (!isVisible) throw new Error("View Node button is not visible!"); await button.click(); + + const isPanelVisible = await waitForElementToBeVisible(this.nodedetailsPanelElements.first()); + if (!isPanelVisible) throw new Error("Node details panel did not appear!"); + const elements = await this.nodedetailsPanelElements.all(); return Promise.all(elements.map(element => element.innerHTML())); } diff --git a/e2e/logic/utils.ts b/e2e/logic/utils.ts index efa4adb8..17b575d8 100644 --- a/e2e/logic/utils.ts +++ b/e2e/logic/utils.ts @@ -34,6 +34,17 @@ export const waitForStableText = async (locator: Locator, timeout: number = 5000 return stableText; }; +export const waitForElementToBeVisible = async (locator:Locator,time=400,retry=5):Promise => { + + while(retry > 0){ + if(await locator.isVisible()){ + return true + } + retry = retry-1 + await delay(time) + } + return false +} export function findNodeByName(nodes: { name: string }[], nodeName: string): any { return nodes.find((node) => node.name === nodeName); diff --git a/e2e/tests/canvas.spec.ts b/e2e/tests/canvas.spec.ts index 022500e3..e54858d8 100644 --- a/e2e/tests/canvas.spec.ts +++ b/e2e/tests/canvas.spec.ts @@ -100,7 +100,7 @@ test.describe("Canvas tests", () => { test(`Verify "Clear graph" button resets canvas view for path ${path.firstNode} and ${path.secondNode}`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); - await codeGraph.clickOnshowPathBtn(); + await codeGraph.clickOnShowPathBtn(); await codeGraph.insertInputForShowPath("1", path.firstNode); await codeGraph.insertInputForShowPath("2", path.secondNode); const initialGraph = await codeGraph.getGraphDetails(); @@ -185,7 +185,7 @@ test.describe("Canvas tests", () => { test(`Verify successful node path connection in canvas between ${firstNode} and ${secondNode} via UI`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); - await codeGraph.clickOnshowPathBtn(); + await codeGraph.clickOnShowPathBtn(); await codeGraph.insertInputForShowPath("1", firstNode); await codeGraph.insertInputForShowPath("2", secondNode); const result = await codeGraph.getGraphDetails(); @@ -200,7 +200,7 @@ test.describe("Canvas tests", () => { test(`Validate node path connection in canvas ui and confirm via api for path ${path.firstNode} and ${path.secondNode}`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); - await codeGraph.clickOnshowPathBtn(); + await codeGraph.clickOnShowPathBtn(); await codeGraph.insertInputForShowPath("1", path.firstNode); await codeGraph.insertInputForShowPath("2", path.secondNode); const result = await codeGraph.getGraphDetails(); diff --git a/e2e/tests/chat.spec.ts b/e2e/tests/chat.spec.ts index 4bce6f0a..d81ac33d 100644 --- a/e2e/tests/chat.spec.ts +++ b/e2e/tests/chat.spec.ts @@ -91,7 +91,7 @@ test.describe("Chat tests", () => { test(`Verify successful node path connection between two nodes in chat for ${path.firstNode} and ${path.secondNode}`, async () => { const chat = await browser.createNewPage(CodeGraph, urls.baseUrl); await chat.selectGraph(GRAPH_ID); - await chat.clickOnshowPathBtn(); + await chat.clickOnShowPathBtn(); await chat.insertInputForShowPath("1", path.firstNode); await chat.insertInputForShowPath("2", path.secondNode); expect(await chat.isNodeVisibleInLastChatPath(path.firstNode)).toBe(true); @@ -103,7 +103,7 @@ test.describe("Chat tests", () => { test(`Verify unsuccessful node path connection between two nodes in chat for ${path.firstNode} and ${path.secondNode}`, async () => { const chat = await browser.createNewPage(CodeGraph, urls.baseUrl); await chat.selectGraph(GRAPH_ID); - await chat.clickOnshowPathBtn(); + await chat.clickOnShowPathBtn(); await chat.insertInputForShowPath("1", path.secondNode); await chat.insertInputForShowPath("2", path.firstNode); await delay(500); @@ -114,7 +114,7 @@ test.describe("Chat tests", () => { test("Validate error notification and its closure when sending an empty question in chat", async () => { const chat = await browser.createNewPage(CodeGraph, urls.baseUrl); await chat.selectGraph(GRAPH_ID); - await chat.clickAskquestionBtn(); + await chat.clickAskQuestionBtn(); expect(await chat.isNotificationError()).toBe(true); await chat.clickOnNotificationErrorCloseBtn(); expect(await chat.isNotificationError()).toBe(false); From 451b02d2562eabab75263945b52c5dbf970bfadb Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Fri, 31 Jan 2025 19:01:50 +0200 Subject: [PATCH 030/189] fix failing tests --- e2e/logic/POM/codeGraph.ts | 13 ++++--------- e2e/tests/navBar.spec.ts | 4 ++-- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 4ee1a0b4..38e9c101 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -259,13 +259,11 @@ export default class CodeGraph extends BasePage { } async clickOnTipBtn(): Promise { - const isVisible = await waitForElementToBeVisible(this.tipBtn); - if (!isVisible) throw new Error("'Tip' button is not visible!"); await this.tipBtn.click(); } async isTipMenuVisible(): Promise { - // await this.page.waitForTimeout(500); + await this.page.waitForTimeout(500); return await waitForElementToBeVisible(this.genericMenu); } @@ -454,19 +452,16 @@ export default class CodeGraph extends BasePage { } async clickOnRemoveNodeViaElementMenu(): Promise { - await this.elementMenu.waitFor({ state: "visible", timeout: 10000}) - const button = this.elementMenuButton("Remove"); + const button = this.elementMenuButton("Remove"); + const isVisible = await waitForElementToBeVisible(button); + if (!isVisible) throw new Error("'View Node' button is not visible!"); await button.click(); } async nodeClick(x: number, y: number): Promise { - await this.page.waitForTimeout(500); - console.log(`Clicking node at: X=${x}, Y=${y}`); await this.canvasElement.hover({ position: { x, y } }); await this.page.waitForTimeout(500); // Allow hover to take effect - console.log("Hover successful"); await this.canvasElement.click({ position: { x, y }, button: 'right' }); - console.log("Right-click performed"); } async selectCodeGraphCheckbox(checkbox: string): Promise { diff --git a/e2e/tests/navBar.spec.ts b/e2e/tests/navBar.spec.ts index 9f294a75..f282ca0a 100644 --- a/e2e/tests/navBar.spec.ts +++ b/e2e/tests/navBar.spec.ts @@ -41,9 +41,9 @@ test.describe(' Navbar tests', () => { test("Validate Tip popup visibility and closure functionality", async () => { const navBar = await browser.createNewPage(CodeGraph, urls.baseUrl); - await navBar.clickonTipBtn(); + await navBar.clickOnTipBtn(); expect(await navBar.isTipMenuVisible()).toBe(true); - await navBar.clickonTipMenuCloseBtn(); + await navBar.clickOnTipMenuCloseBtn(); expect(await navBar.isTipMenuVisible()).toBe(false); }); }); From 8f4343c7d70237970c17e396b76422cced123634 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Sun, 2 Feb 2025 12:40:26 +0200 Subject: [PATCH 031/189] Add CI screenshots on test failure --- .github/workflows/playwright.yml | 13 ++++++++++++- playwright.config.ts | 4 +++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 3893ea77..83f75e3a 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -33,9 +33,20 @@ jobs: npm install npm run build NEXTAUTH_SECRET=SECRET npm start & npx playwright test --reporter=dot,list + - name: Ensure required directories exist + run: | + mkdir -p playwright-report + mkdir -p playwright-report/artifacts - uses: actions/upload-artifact@v4 - if: ${{ !cancelled() }} + if: always() with: name: playwright-report path: playwright-report/ retention-days: 30 + - name: Upload failed test screenshots + if: always() + uses: actions/upload-artifact@v4 + with: + name: failed-test-screenshots + path: playwright-report/artifacts/ + retention-days: 30 diff --git a/playwright.config.ts b/playwright.config.ts index 7a5292d5..2ef25586 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -22,7 +22,8 @@ export default defineConfig({ /* Opt out of parallel tests on CI. */ workers: process.env.CI ? 2 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'html', + reporter: [['html', { outputFolder: 'playwright-report' }]], + outputDir: 'playwright-report/artifacts', /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ @@ -30,6 +31,7 @@ export default defineConfig({ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: 'on-first-retry', + screenshot: 'only-on-failure', }, /* Configure projects for major browsers */ From bbe20700c189a5eae6309dda5bc254d14e033bc3 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Sun, 2 Feb 2025 13:05:10 +0200 Subject: [PATCH 032/189] Update playwright.yml --- .github/workflows/playwright.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 83f75e3a..06b8b283 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -33,7 +33,7 @@ jobs: npm install npm run build NEXTAUTH_SECRET=SECRET npm start & npx playwright test --reporter=dot,list - - name: Ensure required directories exist + - name: Ensure required directories exist run: | mkdir -p playwright-report mkdir -p playwright-report/artifacts From 6a3781327e3f38aeeb72da687ce462888ae3a254 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Sun, 2 Feb 2025 13:55:27 +0200 Subject: [PATCH 033/189] add logging --- e2e/logic/POM/codeGraph.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 38e9c101..22ec6f87 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -454,14 +454,20 @@ export default class CodeGraph extends BasePage { async clickOnRemoveNodeViaElementMenu(): Promise { const button = this.elementMenuButton("Remove"); const isVisible = await waitForElementToBeVisible(button); - if (!isVisible) throw new Error("'View Node' button is not visible!"); + if (!isVisible) throw new Error("'Remove' button is not visible!"); await button.click(); } async nodeClick(x: number, y: number): Promise { + await this.page.waitForTimeout(1000); + console.log("x: ", x, " y: ", y); + await this.canvasElement.hover({ position: { x, y } }); await this.page.waitForTimeout(500); // Allow hover to take effect await this.canvasElement.click({ position: { x, y }, button: 'right' }); + + const isMenuVisible = await waitForElementToBeVisible(this.elementMenu); + if (!isMenuVisible) throw new Error("Element menu did not appear!"); } async selectCodeGraphCheckbox(checkbox: string): Promise { From 44282ad89484eec841053061d1fabc6b68703803 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Sun, 2 Feb 2025 16:10:55 +0200 Subject: [PATCH 034/189] add polling with retries --- e2e/logic/POM/codeGraph.ts | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 22ec6f87..7c4423ae 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -228,6 +228,10 @@ export default class CodeGraph extends BasePage { private get copyToClipboardNodePanelDetails(): Locator { return this.page.locator(`//div[@data-name='node-details-panel']//button[@title='Copy src to clipboard']`); } + + private get nodeToolTip(): Locator { + return this.page.locator("//div[contains(@class, 'graph-tooltip')]"); + } /* NavBar functionality */ async clickOnFalkorDbLogo(): Promise { @@ -459,15 +463,23 @@ export default class CodeGraph extends BasePage { } async nodeClick(x: number, y: number): Promise { - await this.page.waitForTimeout(1000); - console.log("x: ", x, " y: ", y); - - await this.canvasElement.hover({ position: { x, y } }); - await this.page.waitForTimeout(500); // Allow hover to take effect - await this.canvasElement.click({ position: { x, y }, button: 'right' }); - - const isMenuVisible = await waitForElementToBeVisible(this.elementMenu); - if (!isMenuVisible) throw new Error("Element menu did not appear!"); + console.log(`Clicking node at (${x}, ${y})`); + + for (let attempt = 1; attempt <= 5; attempt++) { + await this.canvasElement.hover({ position: { x, y } }); + await this.page.waitForTimeout(500); + + if (await waitForElementToBeVisible(this.nodeToolTip)) { + console.log("Tooltip visible, right-clicking..."); + await this.canvasElement.click({ position: { x, y }, button: 'right' }); + return; + } + + console.warn(`Attempt ${attempt}: Tooltip not visible, retrying...`); + await this.page.waitForTimeout(1000); + } + + throw new Error("Tooltip not visible after multiple attempts!"); } async selectCodeGraphCheckbox(checkbox: string): Promise { From 364ace5b5d982eab56afe6862c803d19e880b57a Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Sun, 2 Feb 2025 17:46:19 +0200 Subject: [PATCH 035/189] add logging and timing --- e2e/logic/POM/codeGraph.ts | 13 +++++++++++-- e2e/tests/nodeDetailsPanel.spec.ts | 9 +++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 7c4423ae..5d92023e 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -481,6 +481,14 @@ export default class CodeGraph extends BasePage { throw new Error("Tooltip not visible after multiple attempts!"); } + + async nodeClicktest(x: number, y: number): Promise { + console.log(`Clicking node at (${x}, ${y})`); + await this.page.waitForTimeout(500); + await this.canvasElement.hover({ position: { x, y } }); + await this.canvasElement.click({ position: { x, y }, button: 'right' }); + await this.page.waitForTimeout(5000); + } async selectCodeGraphCheckbox(checkbox: string): Promise { await this.codeGraphCheckbox(checkbox).click(); @@ -576,8 +584,8 @@ export default class CodeGraph extends BasePage { async getGraphDetails(): Promise { await this.canvasElementBeforeGraphSelection.waitFor({ state: 'detached' }); - await this.page.waitForTimeout(2000); //canvas animation - await this.page.waitForFunction(() => !!window.graph); + await this.page.waitForTimeout(3000); //canvas animation + await this.page.waitForFunction(() => window.graph && window.graph.elements.nodes.length > 0); const graphData = await this.page.evaluate(() => { return window.graph; @@ -587,6 +595,7 @@ export default class CodeGraph extends BasePage { } async transformNodeCoordinates(graphData: any): Promise { + await this.page.waitForTimeout(3000); const { canvasLeft, canvasTop, canvasWidth, canvasHeight, transform } = await this.canvasElement.evaluate((canvas: HTMLCanvasElement) => { const rect = canvas.getBoundingClientRect(); const ctx = canvas.getContext('2d'); diff --git a/e2e/tests/nodeDetailsPanel.spec.ts b/e2e/tests/nodeDetailsPanel.spec.ts index 5f69afd4..b37f2483 100644 --- a/e2e/tests/nodeDetailsPanel.spec.ts +++ b/e2e/tests/nodeDetailsPanel.spec.ts @@ -37,8 +37,11 @@ test.describe("Node details panel tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); const graphData = await codeGraph.getGraphDetails(); + const nod = findNodeByName(graphData.elements.nodes, node.nodeName); + console.log("before x:", nod.x, " before y: ",nod.y); const convertCoordinates = await codeGraph.transformNodeCoordinates(graphData); const node1 = findNodeByName(convertCoordinates, node.nodeName); + console.log("after test: ", node1.screenX, " ", node1.screenY); await codeGraph.nodeClick(node1.screenX, node1.screenY); await codeGraph.clickOnViewNode(); await codeGraph.clickOnNodeDetailsCloseBtn(); @@ -51,8 +54,11 @@ test.describe("Node details panel tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); const graphData = await codeGraph.getGraphDetails(); + const nod = findNodeByName(graphData.elements.nodes, node.nodeName); + console.log("before x:", nod.x, " before y: ",nod.y); const convertCoordinates = await codeGraph.transformNodeCoordinates(graphData); const node1 = findNodeByName(convertCoordinates, node.nodeName); + console.log("after test: ", node1.screenX, " ", node1.screenY); await codeGraph.nodeClick(node1.screenX, node1.screenY); expect(await codeGraph.getNodeDetailsHeader()).toContain(node.nodeName.toUpperCase()) }) @@ -63,8 +69,11 @@ test.describe("Node details panel tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); const graphData = await codeGraph.getGraphDetails(); + const nod = findNodeByName(graphData.elements.nodes, node.nodeName); + console.log("before x:", nod.x, " before y: ",nod.y); const convertCoordinates = await codeGraph.transformNodeCoordinates(graphData); const nodeData = findNodeByName(convertCoordinates, node.nodeName); + console.log("after test: ", nodeData.screenX, " ", nodeData.screenY); await codeGraph.nodeClick(nodeData.screenX, nodeData.screenY); await codeGraph.clickOnViewNode(); const result = await codeGraph.clickOnCopyToClipboardNodePanelDetails(); From 0fefd041332c9acf931cb9b14553564c6c9f68a6 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Sun, 2 Feb 2025 20:51:49 +0200 Subject: [PATCH 036/189] add more logging improve transformnNode --- e2e/logic/POM/codeGraph.ts | 65 ++++++++++++++++++++---------- e2e/tests/canvas.spec.ts | 9 +++++ e2e/tests/nodeDetailsPanel.spec.ts | 7 ++++ 3 files changed, 60 insertions(+), 21 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 5d92023e..a0ef2e73 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -595,31 +595,54 @@ export default class CodeGraph extends BasePage { } async transformNodeCoordinates(graphData: any): Promise { - await this.page.waitForTimeout(3000); - const { canvasLeft, canvasTop, canvasWidth, canvasHeight, transform } = await this.canvasElement.evaluate((canvas: HTMLCanvasElement) => { - const rect = canvas.getBoundingClientRect(); - const ctx = canvas.getContext('2d'); - const transform = ctx?.getTransform()!; - return { - canvasLeft: rect.left, - canvasTop: rect.top, - canvasWidth: rect.width, - canvasHeight: rect.height, - transform, - }; - }); - - const screenCoordinates = graphData.elements.nodes.map((node: any) => { - const adjustedX = node.x * transform.a + transform.e; + let maxRetries = 5; + let transform = null; + let canvasRect = null; + + // Ensure the graph is fully loaded before proceeding + await this.page.waitForFunction(() => window.graph && window.graph.elements?.nodes?.length > 0); + await this.page.waitForTimeout(3000); // Wait for canvas animations to settle + + for (let attempt = 1; attempt <= maxRetries; attempt++) { + await this.page.waitForTimeout(1000); // Allow further stabilization before fetching data + + // Fetch canvas properties + const result = await this.canvasElement.evaluate((canvas: HTMLCanvasElement) => { + const rect = canvas.getBoundingClientRect(); + const ctx = canvas.getContext('2d'); + return { + canvasLeft: rect.left, + canvasTop: rect.top, + canvasWidth: rect.width, + canvasHeight: rect.height, + transform: ctx?.getTransform() || null, // Ensure transform is not null + }; + }); + + if (!result.transform) { + console.warn(`Attempt ${attempt}: Transform not available yet, retrying...`); + continue; // Retry if transform is not available + } + + // If we successfully get a transform, store and break out of retry loop + transform = result.transform; + canvasRect = result; + break; + } + + if (!transform) throw new Error("Canvas transform data not available after multiple attempts!"); + + // Convert graph coordinates to screen coordinates + return graphData.elements.nodes.map((node: any) => { + const adjustedX = node.x * transform.a + transform.e; const adjustedY = node.y * transform.d + transform.f; - const screenX = canvasLeft + adjustedX - 35; - const screenY = canvasTop + adjustedY - 190; + const screenX = canvasRect!.canvasLeft + adjustedX - 35; + const screenY = canvasRect!.canvasTop + adjustedY - 190; - return {...node, screenX, screenY,}; + return { ...node, screenX, screenY }; }); - - return screenCoordinates; } + async getCanvasScaling(): Promise<{ scaleX: number; scaleY: number }> { const { scaleX, scaleY } = await this.canvasElement.evaluate((canvas: HTMLCanvasElement) => { diff --git a/e2e/tests/canvas.spec.ts b/e2e/tests/canvas.spec.ts index e54858d8..d5048c6b 100644 --- a/e2e/tests/canvas.spec.ts +++ b/e2e/tests/canvas.spec.ts @@ -58,8 +58,11 @@ test.describe("Canvas tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); const initialGraph = await codeGraph.getGraphDetails(); + const nod = findNodeByName(initialGraph.elements.nodes, node.nodeName); + console.log("before x:", nod.x, " before y: ",nod.y); const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); const targetNode = findNodeByName(convertCoordinates, node.nodeName); + console.log("after test: ", targetNode.screenX, " ", targetNode.screenY); await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); await codeGraph.clickOnRemoveNodeViaElementMenu(); const updatedGraph = await codeGraph.getGraphDetails(); @@ -73,8 +76,11 @@ test.describe("Canvas tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); const initialGraph = await codeGraph.getGraphDetails(); + const nod = findNodeByName(initialGraph.elements.nodes, node.nodeName); + console.log("before x:", nod.x, " before y: ",nod.y); const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); const targetNode = findNodeByName(convertCoordinates, node.nodeName); + console.log("after test: ", targetNode.screenX, " ", targetNode.screenY); await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); await codeGraph.clickOnRemoveNodeViaElementMenu(); await codeGraph.clickOnUnhideNodesBtn(); @@ -170,8 +176,11 @@ test.describe("Canvas tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); const graphData = await codeGraph.getGraphDetails(); + const nod = findNodeByName(graphData.elements.nodes, node.nodeName); + console.log("before x:", nod.x, " before y: ",nod.y); const convertCoordinates = await codeGraph.transformNodeCoordinates(graphData); const targetNode = findNodeByName(convertCoordinates, node.nodeName); + console.log("after x:", targetNode.x, " after y: ",targetNode.y); await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); const result = await codeGraph.clickOnCopyToClipboard(); const api = new ApiCalls(); diff --git a/e2e/tests/nodeDetailsPanel.spec.ts b/e2e/tests/nodeDetailsPanel.spec.ts index b37f2483..f9fb104e 100644 --- a/e2e/tests/nodeDetailsPanel.spec.ts +++ b/e2e/tests/nodeDetailsPanel.spec.ts @@ -23,8 +23,11 @@ test.describe("Node details panel tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); const graphData = await codeGraph.getGraphDetails(); + const nod = findNodeByName(graphData.elements.nodes, node.nodeName); + console.log("before x:", nod.x, " before y: ",nod.y); const convertCoordinates = await codeGraph.transformNodeCoordinates(graphData); const targetNode = findNodeByName(convertCoordinates, node.nodeName); + console.log("after test: ", targetNode.screenX, " ", targetNode.screenY); expect(targetNode).toBeDefined(); await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); await codeGraph.clickOnViewNode(); @@ -89,8 +92,12 @@ test.describe("Node details panel tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); const graphData = await codeGraph.getGraphDetails(); + const nod = findNodeByName(graphData.elements.nodes, node.nodeName); + console.log("before x:", nod.x, " before y: ",nod.y); + const convertCoordinates = await codeGraph.transformNodeCoordinates(graphData); const node1 = findNodeByName(convertCoordinates, node.nodeName); + console.log("after test: ", node1.screenX, " ", node1.screenY); const api = new ApiCalls(); const response = await api.getProject(PROJECT_NAME); const data: any = response.result.entities.nodes; From c214063a727648e3bee8a3d3eecb29dc92b652cd Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Mon, 3 Feb 2025 13:54:59 +0200 Subject: [PATCH 037/189] Update testData.ts --- e2e/config/testData.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/config/testData.ts b/e2e/config/testData.ts index dab5ebf7..3cb008e2 100644 --- a/e2e/config/testData.ts +++ b/e2e/config/testData.ts @@ -20,7 +20,7 @@ export const nodesPath: { firstNode: string; secondNode: string }[] = [ ]; export const nodes: { nodeName: string; }[] = [ - { nodeName: "import_data"}, + { nodeName: "ask"}, { nodeName: "add_edge" }, { nodeName: "test_kg_delete"}, { nodeName: "list_graphs"} From 681e65537db2cad94a308ad7af3c54b4e0ca0b85 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Mon, 3 Feb 2025 15:12:45 +0200 Subject: [PATCH 038/189] remove logging, increase workers --- e2e/logic/POM/codeGraph.ts | 29 +++++++++-------------------- e2e/tests/canvas.spec.ts | 9 --------- e2e/tests/nodeDetailsPanel.spec.ts | 18 +----------------- playwright.config.ts | 4 ++-- 4 files changed, 12 insertions(+), 48 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index a0ef2e73..7cc9ccd7 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -462,23 +462,18 @@ export default class CodeGraph extends BasePage { await button.click(); } - async nodeClick(x: number, y: number): Promise { - console.log(`Clicking node at (${x}, ${y})`); - - for (let attempt = 1; attempt <= 5; attempt++) { + async nodeClick(x: number, y: number): Promise { + for (let attempt = 1; attempt <= 2; attempt++) { await this.canvasElement.hover({ position: { x, y } }); await this.page.waitForTimeout(500); if (await waitForElementToBeVisible(this.nodeToolTip)) { - console.log("Tooltip visible, right-clicking..."); await this.canvasElement.click({ position: { x, y }, button: 'right' }); return; } - - console.warn(`Attempt ${attempt}: Tooltip not visible, retrying...`); await this.page.waitForTimeout(1000); } - + throw new Error("Tooltip not visible after multiple attempts!"); } @@ -584,8 +579,8 @@ export default class CodeGraph extends BasePage { async getGraphDetails(): Promise { await this.canvasElementBeforeGraphSelection.waitFor({ state: 'detached' }); - await this.page.waitForTimeout(3000); //canvas animation await this.page.waitForFunction(() => window.graph && window.graph.elements.nodes.length > 0); + await this.page.waitForTimeout(2000); //canvas animation const graphData = await this.page.evaluate(() => { return window.graph; @@ -595,18 +590,14 @@ export default class CodeGraph extends BasePage { } async transformNodeCoordinates(graphData: any): Promise { - let maxRetries = 5; + let maxRetries = 3; let transform = null; let canvasRect = null; - - // Ensure the graph is fully loaded before proceeding await this.page.waitForFunction(() => window.graph && window.graph.elements?.nodes?.length > 0); - await this.page.waitForTimeout(3000); // Wait for canvas animations to settle for (let attempt = 1; attempt <= maxRetries; attempt++) { - await this.page.waitForTimeout(1000); // Allow further stabilization before fetching data + await this.page.waitForTimeout(1000); - // Fetch canvas properties const result = await this.canvasElement.evaluate((canvas: HTMLCanvasElement) => { const rect = canvas.getBoundingClientRect(); const ctx = canvas.getContext('2d'); @@ -615,24 +606,22 @@ export default class CodeGraph extends BasePage { canvasTop: rect.top, canvasWidth: rect.width, canvasHeight: rect.height, - transform: ctx?.getTransform() || null, // Ensure transform is not null + transform: ctx?.getTransform() || null, }; }); if (!result.transform) { console.warn(`Attempt ${attempt}: Transform not available yet, retrying...`); - continue; // Retry if transform is not available + continue; } - // If we successfully get a transform, store and break out of retry loop transform = result.transform; canvasRect = result; break; } if (!transform) throw new Error("Canvas transform data not available after multiple attempts!"); - - // Convert graph coordinates to screen coordinates + return graphData.elements.nodes.map((node: any) => { const adjustedX = node.x * transform.a + transform.e; const adjustedY = node.y * transform.d + transform.f; diff --git a/e2e/tests/canvas.spec.ts b/e2e/tests/canvas.spec.ts index d5048c6b..e54858d8 100644 --- a/e2e/tests/canvas.spec.ts +++ b/e2e/tests/canvas.spec.ts @@ -58,11 +58,8 @@ test.describe("Canvas tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); const initialGraph = await codeGraph.getGraphDetails(); - const nod = findNodeByName(initialGraph.elements.nodes, node.nodeName); - console.log("before x:", nod.x, " before y: ",nod.y); const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); const targetNode = findNodeByName(convertCoordinates, node.nodeName); - console.log("after test: ", targetNode.screenX, " ", targetNode.screenY); await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); await codeGraph.clickOnRemoveNodeViaElementMenu(); const updatedGraph = await codeGraph.getGraphDetails(); @@ -76,11 +73,8 @@ test.describe("Canvas tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); const initialGraph = await codeGraph.getGraphDetails(); - const nod = findNodeByName(initialGraph.elements.nodes, node.nodeName); - console.log("before x:", nod.x, " before y: ",nod.y); const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); const targetNode = findNodeByName(convertCoordinates, node.nodeName); - console.log("after test: ", targetNode.screenX, " ", targetNode.screenY); await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); await codeGraph.clickOnRemoveNodeViaElementMenu(); await codeGraph.clickOnUnhideNodesBtn(); @@ -176,11 +170,8 @@ test.describe("Canvas tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); const graphData = await codeGraph.getGraphDetails(); - const nod = findNodeByName(graphData.elements.nodes, node.nodeName); - console.log("before x:", nod.x, " before y: ",nod.y); const convertCoordinates = await codeGraph.transformNodeCoordinates(graphData); const targetNode = findNodeByName(convertCoordinates, node.nodeName); - console.log("after x:", targetNode.x, " after y: ",targetNode.y); await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); const result = await codeGraph.clickOnCopyToClipboard(); const api = new ApiCalls(); diff --git a/e2e/tests/nodeDetailsPanel.spec.ts b/e2e/tests/nodeDetailsPanel.spec.ts index f9fb104e..3aea588c 100644 --- a/e2e/tests/nodeDetailsPanel.spec.ts +++ b/e2e/tests/nodeDetailsPanel.spec.ts @@ -23,11 +23,8 @@ test.describe("Node details panel tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); const graphData = await codeGraph.getGraphDetails(); - const nod = findNodeByName(graphData.elements.nodes, node.nodeName); - console.log("before x:", nod.x, " before y: ",nod.y); const convertCoordinates = await codeGraph.transformNodeCoordinates(graphData); const targetNode = findNodeByName(convertCoordinates, node.nodeName); - console.log("after test: ", targetNode.screenX, " ", targetNode.screenY); expect(targetNode).toBeDefined(); await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); await codeGraph.clickOnViewNode(); @@ -40,11 +37,8 @@ test.describe("Node details panel tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); const graphData = await codeGraph.getGraphDetails(); - const nod = findNodeByName(graphData.elements.nodes, node.nodeName); - console.log("before x:", nod.x, " before y: ",nod.y); const convertCoordinates = await codeGraph.transformNodeCoordinates(graphData); const node1 = findNodeByName(convertCoordinates, node.nodeName); - console.log("after test: ", node1.screenX, " ", node1.screenY); await codeGraph.nodeClick(node1.screenX, node1.screenY); await codeGraph.clickOnViewNode(); await codeGraph.clickOnNodeDetailsCloseBtn(); @@ -57,11 +51,8 @@ test.describe("Node details panel tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); const graphData = await codeGraph.getGraphDetails(); - const nod = findNodeByName(graphData.elements.nodes, node.nodeName); - console.log("before x:", nod.x, " before y: ",nod.y); const convertCoordinates = await codeGraph.transformNodeCoordinates(graphData); const node1 = findNodeByName(convertCoordinates, node.nodeName); - console.log("after test: ", node1.screenX, " ", node1.screenY); await codeGraph.nodeClick(node1.screenX, node1.screenY); expect(await codeGraph.getNodeDetailsHeader()).toContain(node.nodeName.toUpperCase()) }) @@ -72,11 +63,8 @@ test.describe("Node details panel tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); const graphData = await codeGraph.getGraphDetails(); - const nod = findNodeByName(graphData.elements.nodes, node.nodeName); - console.log("before x:", nod.x, " before y: ",nod.y); const convertCoordinates = await codeGraph.transformNodeCoordinates(graphData); const nodeData = findNodeByName(convertCoordinates, node.nodeName); - console.log("after test: ", nodeData.screenX, " ", nodeData.screenY); await codeGraph.nodeClick(nodeData.screenX, nodeData.screenY); await codeGraph.clickOnViewNode(); const result = await codeGraph.clickOnCopyToClipboardNodePanelDetails(); @@ -91,13 +79,9 @@ test.describe("Node details panel tests", () => { test(`Validate view node panel keys via api for ${node.nodeName}`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); - const graphData = await codeGraph.getGraphDetails(); - const nod = findNodeByName(graphData.elements.nodes, node.nodeName); - console.log("before x:", nod.x, " before y: ",nod.y); - + const graphData = await codeGraph.getGraphDetails(); const convertCoordinates = await codeGraph.transformNodeCoordinates(graphData); const node1 = findNodeByName(convertCoordinates, node.nodeName); - console.log("after test: ", node1.screenX, " ", node1.screenY); const api = new ApiCalls(); const response = await api.getProject(PROJECT_NAME); const data: any = response.result.entities.nodes; diff --git a/playwright.config.ts b/playwright.config.ts index 2ef25586..8b5b1550 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -16,11 +16,11 @@ export default defineConfig({ /* Run tests in files in parallel */ fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, + forbidOnly: !!process.env.CI, /* Retry on CI only */ retries: process.env.CI ? 2 : 0, /* Opt out of parallel tests on CI. */ - workers: process.env.CI ? 2 : undefined, + workers: process.env.CI ? 3 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: [['html', { outputFolder: 'playwright-report' }]], outputDir: 'playwright-report/artifacts', From 97997146a7bc1fff2afc08416cb7fd5d4ac12cb4 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Thu, 6 Feb 2025 12:08:18 +0200 Subject: [PATCH 039/189] fix build --- app/components/code-graph.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 1dad952d..8e0341f8 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -243,7 +243,7 @@ export function CodeGraph({ setData({ ...graph.Elements }) } - setSearchNode(n) + setSearchNode(chartNode) setTimeout(() => { chart.zoomToFit(1000, 150, (n: NodeObject) => n.id === chartNode!.id); }, 0) From 1f6c14b9b72363085e7f7ba668d4753f687d0feb Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Tue, 11 Feb 2025 11:33:18 +0200 Subject: [PATCH 040/189] remove logs and debugs --- app/components/dataPanel.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/components/dataPanel.tsx b/app/components/dataPanel.tsx index 21469cb5..2e216405 100644 --- a/app/components/dataPanel.tsx +++ b/app/components/dataPanel.tsx @@ -35,16 +35,12 @@ const excludedProperties = [ export default function DataPanel({ obj, setObj, url }: Props) { - debugger - if (!obj) return null; const type = "category" in obj const label = type ? `${obj.category}: ${obj.name}` : obj.label const object = Object.entries(obj).filter(([k]) => !excludedProperties.includes(k)) - console.log(obj) - return (
From 86bd8b1efc8d55138a91177bd1f02cc817c2f189 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Wed, 12 Feb 2025 10:09:21 +0200 Subject: [PATCH 041/189] bump all available dependencies --- package-lock.json | 3475 ++++++++++++++++----------------------------- package.json | 46 +- 2 files changed, 1266 insertions(+), 2255 deletions(-) diff --git a/package-lock.json b/package-lock.json index 11fe98ce..3577dcc2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,52 +8,51 @@ "name": "code-graph", "version": "0.2.0", "dependencies": { - "@radix-ui/react-checkbox": "^1.1.2", - "@radix-ui/react-dialog": "^1.1.2", - "@radix-ui/react-dropdown-menu": "^2.1.2", - "@radix-ui/react-hover-card": "^1.1.2", - "@radix-ui/react-progress": "^1.1.0", - "@radix-ui/react-select": "^2.1.2", + "@radix-ui/react-checkbox": "^1.1.4", + "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-dropdown-menu": "^2.1.6", + "@radix-ui/react-hover-card": "^1.1.6", + "@radix-ui/react-progress": "^1.1.2", + "@radix-ui/react-select": "^2.1.6", "@radix-ui/react-slot": "^1.0.2", - "@radix-ui/react-toast": "^1.2.2", - "@radix-ui/react-tooltip": "^1.1.4", + "@radix-ui/react-toast": "^1.2.6", + "@radix-ui/react-tooltip": "^1.1.8", "@types/react-gtm-module": "^2.0.4", "autoprefixer": "^10.4.20", "canvas2svg": "^1.0.16", "class-variance-authority": "^0.7.1", - "clsx": "^2.1.0", + "clsx": "^2.1.1", "html2canvas": "^1.4.1", "lucide-react": "^0.441.0", - "next": "^15.1.2", + "next": "^15.1.7", "playwright": "^1.49.1", - "react": "^18", - "react-dom": "^18", - "react-force-graph-2d": "^1.25.8", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-force-graph-2d": "^1.27.0", "react-gtm-module": "^2.0.11", "react-json-tree": "^0.19.0", - "react-resizable-panels": "^2.0.20", + "react-resizable-panels": "^2.1.7", "react-syntax-highlighter": "^15.6.1", "react-type-animation": "^3.2.0", - "tailwind-merge": "^2.5.5", + "tailwind-merge": "^2.6.0", "tailwindcss-animate": "^1.0.7" }, "devDependencies": { - "@playwright/test": "^1.49.1", - "@types/node": "^22.10.2", - "@types/react": "^18", - "@types/react-dom": "^18", + "@playwright/test": "^1.50.1", + "@types/node": "^22.13.1", + "@types/react": "^18.3.18", + "@types/react-dom": "^18.3.5", "@types/react-syntax-highlighter": "^15.5.13", - "eslint": "^9", - "eslint-config-next": "^15.1.2", - "tailwindcss": "^3.4.3", - "typescript": "^5" + "eslint": "^9.20.1", + "eslint-config-next": "^15.1.7", + "tailwindcss": "^3.4.17", + "typescript": "^5.7.3" } }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "license": "MIT", "engines": { "node": ">=10" }, @@ -62,9 +61,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", - "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz", + "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -82,39 +81,51 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", "dev": true, - "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@eslint-community/regexpp": { "version": "4.12.1", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, - "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/config-array": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.0.tgz", - "integrity": "sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", + "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.4", + "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -123,11 +134,13 @@ } }, "node_modules/@eslint/core": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.0.tgz", - "integrity": "sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.11.0.tgz", + "integrity": "sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA==", "dev": true, - "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -137,7 +150,6 @@ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, - "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -157,62 +169,69 @@ } }, "node_modules/@eslint/js": { - "version": "9.15.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.15.0.tgz", - "integrity": "sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==", + "version": "9.20.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.20.0.tgz", + "integrity": "sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ==", "dev": true, - "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", "dev": true, - "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", - "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", + "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", "dev": true, - "license": "Apache-2.0", "dependencies": { + "@eslint/core": "^0.10.0", "levn": "^0.4.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", + "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@floating-ui/core": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.7.tgz", - "integrity": "sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==", - "license": "MIT", + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz", + "integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==", "dependencies": { - "@floating-ui/utils": "^0.2.7" + "@floating-ui/utils": "^0.2.9" } }, "node_modules/@floating-ui/dom": { - "version": "1.6.10", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.10.tgz", - "integrity": "sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==", - "license": "MIT", + "version": "1.6.13", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz", + "integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==", "dependencies": { "@floating-ui/core": "^1.6.0", - "@floating-ui/utils": "^0.2.7" + "@floating-ui/utils": "^0.2.9" } }, "node_modules/@floating-ui/react-dom": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz", - "integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==", - "license": "MIT", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", "dependencies": { "@floating-ui/dom": "^1.0.0" }, @@ -222,17 +241,15 @@ } }, "node_modules/@floating-ui/utils": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.7.tgz", - "integrity": "sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==", - "license": "MIT" + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", + "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==" }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, - "license": "Apache-2.0", "engines": { "node": ">=18.18.0" } @@ -242,7 +259,6 @@ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, - "license": "Apache-2.0", "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" @@ -256,7 +272,6 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "dev": true, - "license": "Apache-2.0", "engines": { "node": ">=18.18" }, @@ -270,7 +285,6 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -284,7 +298,6 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", "dev": true, - "license": "Apache-2.0", "engines": { "node": ">=18.18" }, @@ -639,7 +652,6 @@ "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "license": "ISC", "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -652,38 +664,10 @@ "node": ">=12" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "license": "MIT", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -697,7 +681,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -706,7 +689,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -714,65 +696,35 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "license": "MIT" + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@next/env": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.1.2.tgz", - "integrity": "sha512-Hm3jIGsoUl6RLB1vzY+dZeqb+/kWPZ+h34yiWxW0dV87l8Im/eMOwpOA+a0L78U0HM04syEjXuRlCozqpwuojQ==" + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.1.7.tgz", + "integrity": "sha512-d9jnRrkuOH7Mhi+LHav2XW91HOgTAWHxjMPkXMGBc9B2b7614P7kjt8tAplRvJpbSt4nbO1lugcT/kAaWzjlLQ==" }, "node_modules/@next/eslint-plugin-next": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.1.2.tgz", - "integrity": "sha512-sgfw3+WdaYOGPKCvM1L+UucBmRfh8V2Ygefp7ELON0+0vY7uohQwXXnVWg3rY7mXDKharQR3o7uedpfvnU2hlQ==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.1.7.tgz", + "integrity": "sha512-kRP7RjSxfTO13NE317ek3mSGzoZlI33nc/i5hs1KaWpK+egs85xg0DJ4p32QEiHnR0mVjuUfhRIun7awqfL7pQ==", "dev": true, "dependencies": { "fast-glob": "3.3.1" } }, - "node_modules/@next/eslint-plugin-next/node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/@next/eslint-plugin-next/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/@next/swc-darwin-arm64": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.1.2.tgz", - "integrity": "sha512-b9TN7q+j5/7+rGLhFAVZiKJGIASuo8tWvInGfAd8wsULjB1uNGRCj1z1WZwwPWzVQbIKWFYqc+9L7W09qwt52w==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.1.7.tgz", + "integrity": "sha512-hPFwzPJDpA8FGj7IKV3Yf1web3oz2YsR8du4amKw8d+jAOHfYHYFpMkoF6vgSY4W6vB29RtZEklK9ayinGiCmQ==", "cpu": [ "arm64" ], @@ -785,9 +737,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.1.2.tgz", - "integrity": "sha512-caR62jNDUCU+qobStO6YJ05p9E+LR0EoXh1EEmyU69cYydsAy7drMcOlUlRtQihM6K6QfvNwJuLhsHcCzNpqtA==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.1.7.tgz", + "integrity": "sha512-2qoas+fO3OQKkU0PBUfwTiw/EYpN+kdAx62cePRyY1LqKtP09Vp5UcUntfZYajop5fDFTjSxCHfZVRxzi+9FYQ==", "cpu": [ "x64" ], @@ -800,9 +752,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.1.2.tgz", - "integrity": "sha512-fHHXBusURjBmN6VBUtu6/5s7cCeEkuGAb/ZZiGHBLVBXMBy4D5QpM8P33Or8JD1nlOjm/ZT9sEE5HouQ0F+hUA==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.1.7.tgz", + "integrity": "sha512-sKLLwDX709mPdzxMnRIXLIT9zaX2w0GUlkLYQnKGoXeWUhcvpCrK+yevcwCJPdTdxZEUA0mOXGLdPsGkudGdnA==", "cpu": [ "arm64" ], @@ -815,9 +767,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.1.2.tgz", - "integrity": "sha512-9CF1Pnivij7+M3G74lxr+e9h6o2YNIe7QtExWq1KUK4hsOLTBv6FJikEwCaC3NeYTflzrm69E5UfwEAbV2U9/g==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.1.7.tgz", + "integrity": "sha512-zblK1OQbQWdC8fxdX4fpsHDw+VSpBPGEUX4PhSE9hkaWPrWoeIJn+baX53vbsbDRaDKd7bBNcXRovY1hEhFd7w==", "cpu": [ "arm64" ], @@ -830,9 +782,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.1.2.tgz", - "integrity": "sha512-tINV7WmcTUf4oM/eN3Yuu/f8jQ5C6AkueZPKeALs/qfdfX57eNv4Ij7rt0SA6iZ8+fMobVfcFVv664Op0caCCg==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.1.7.tgz", + "integrity": "sha512-GOzXutxuLvLHFDAPsMP2zDBMl1vfUHHpdNpFGhxu90jEzH6nNIgmtw/s1MDwpTOiM+MT5V8+I1hmVFeAUhkbgQ==", "cpu": [ "x64" ], @@ -845,9 +797,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.1.2.tgz", - "integrity": "sha512-jf2IseC4WRsGkzeUw/cK3wci9pxR53GlLAt30+y+B+2qAQxMw6WAC3QrANIKxkcoPU3JFh/10uFfmoMDF9JXKg==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.1.7.tgz", + "integrity": "sha512-WrZ7jBhR7ATW1z5iEQ0ZJfE2twCNSXbpCSaAunF3BKcVeHFADSI/AW1y5Xt3DzTqPF1FzQlwQTewqetAABhZRQ==", "cpu": [ "x64" ], @@ -860,9 +812,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.1.2.tgz", - "integrity": "sha512-wvg7MlfnaociP7k8lxLX4s2iBJm4BrNiNFhVUY+Yur5yhAJHfkS8qPPeDEUH8rQiY0PX3u/P7Q/wcg6Mv6GSAA==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.1.7.tgz", + "integrity": "sha512-LDnj1f3OVbou1BqvvXVqouJZKcwq++mV2F+oFHptToZtScIEnhNRJAhJzqAtTE2dB31qDYL45xJwrc+bLeKM2Q==", "cpu": [ "arm64" ], @@ -875,9 +827,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.1.2.tgz", - "integrity": "sha512-D3cNA8NoT3aWISWmo7HF5Eyko/0OdOO+VagkoJuiTk7pyX3P/b+n8XA/MYvyR+xSVcbKn68B1rY9fgqjNISqzQ==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.1.7.tgz", + "integrity": "sha512-dC01f1quuf97viOfW05/K8XYv2iuBgAxJZl7mbCKEjMgdQl5JjAKJ0D2qMKZCgPWDeFbFT0Q0nYWwytEW0DWTQ==", "cpu": [ "x64" ], @@ -893,7 +845,6 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -906,7 +857,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "license": "MIT", "engines": { "node": ">= 8" } @@ -915,7 +865,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -924,23 +873,31 @@ "node": ">= 8" } }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "engines": { + "node": ">=12.4.0" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "license": "MIT", "optional": true, "engines": { "node": ">=14" } }, "node_modules/@playwright/test": { - "version": "1.49.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.1.tgz", - "integrity": "sha512-Ky+BVzPz8pL6PQxHqNRW1k3mIyv933LML7HktS8uik0bUXNCdPhoS/kLihiO1tMf/egaJb4IutXd7UywvXEW+g==", + "version": "1.50.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.50.1.tgz", + "integrity": "sha512-Jii3aBg+CEDpgnuDxEp/h7BimHcUTDlpEtce89xEumlJ5ef2hqepZ+PWp1DDpYC/VO9fmWVI1IlEaoI5fK9FXQ==", "devOptional": true, "dependencies": { - "playwright": "1.49.1" + "playwright": "1.50.1" }, "bin": { "playwright": "cli.js" @@ -952,22 +909,19 @@ "node_modules/@radix-ui/number": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz", - "integrity": "sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==", - "license": "MIT" + "integrity": "sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==" }, "node_modules/@radix-ui/primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", - "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==", - "license": "MIT" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", + "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==" }, "node_modules/@radix-ui/react-arrow": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz", - "integrity": "sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==", - "license": "MIT", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.2.tgz", + "integrity": "sha512-G+KcpzXHq24iH0uGG/pF8LyzpFJYGD4RfLjCIBfGdSLXvjLHST31RUiRVrupIBMvIppMgSzQ6l66iAxl03tdlg==", "dependencies": { - "@radix-ui/react-primitive": "2.0.0" + "@radix-ui/react-primitive": "2.0.2" }, "peerDependencies": { "@types/react": "*", @@ -985,15 +939,15 @@ } }, "node_modules/@radix-ui/react-checkbox": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.2.tgz", - "integrity": "sha512-/i0fl686zaJbDQLNKrkCbMyDm6FQMt4jg323k7HuqitoANm9sE23Ql8yOK3Wusk34HSLKDChhMux05FnP6KUkw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.4.tgz", + "integrity": "sha512-wP0CPAHq+P5I4INKe3hJrIa1WoNqqrejzW+zoU0rOvo1b9gDEJJFl2rYfO1PYJUQCc2H1WZxIJmyv9BS8i5fLw==", "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-presence": "1.1.1", - "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-controllable-state": "1.1.0", "@radix-ui/react-use-previous": "1.1.0", "@radix-ui/react-use-size": "1.1.0" @@ -1013,53 +967,15 @@ } } }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-context": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", - "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-presence": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz", - "integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, "node_modules/@radix-ui/react-collection": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz", - "integrity": "sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==", - "license": "MIT", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.2.tgz", + "integrity": "sha512-9z54IEKRxIa9VityapoEYMuByaG42iSy1ZXlY2KcuLSEtq8x4987/N6m15ppoMffgZX72gER2uHe1D9Y6Unlcw==", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-slot": "1.1.0" + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-slot": "1.1.2" }, "peerDependencies": { "@types/react": "*", @@ -1077,10 +993,9 @@ } }, "node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", - "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", - "license": "MIT", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", + "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -1092,10 +1007,9 @@ } }, "node_modules/@radix-ui/react-context": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", - "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", - "license": "MIT", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -1107,24 +1021,24 @@ } }, "node_modules/@radix-ui/react-dialog": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.2.tgz", - "integrity": "sha512-Yj4dZtqa2o+kG61fzB0H2qUvmwBA2oyQroGLyNtBj1beo1khoQ3q1a2AO8rrQYjd8256CO9+N8L9tvsS+bnIyA==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.6.tgz", + "integrity": "sha512-/IVhJV5AceX620DUJ4uYVMymzsipdKBzo3edo+omeskCKGm9FRHM0ebIdbPnlQVJqyuHbuBltQUOG2mOTq2IYw==", "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.5", "@radix-ui/react-focus-guards": "1.1.1", - "@radix-ui/react-focus-scope": "1.1.0", + "@radix-ui/react-focus-scope": "1.1.2", "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-portal": "1.1.2", - "@radix-ui/react-presence": "1.1.1", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-slot": "1.1.0", + "@radix-ui/react-portal": "1.1.4", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-slot": "1.1.2", "@radix-ui/react-use-controllable-state": "1.1.0", - "aria-hidden": "^1.1.1", - "react-remove-scroll": "2.6.0" + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", @@ -1141,10 +1055,10 @@ } } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-context": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", - "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "node_modules/@radix-ui/react-direction": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", + "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -1155,14 +1069,14 @@ } } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz", - "integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==", + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz", + "integrity": "sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg==", "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-escape-keydown": "1.1.0" }, @@ -1181,13 +1095,18 @@ } } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-portal": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz", - "integrity": "sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==", + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.6.tgz", + "integrity": "sha512-no3X7V5fD487wab/ZYSHXq3H37u4NVeLDKI/Ks724X/eEFSSEFYZxWgsIlr1UBeEyDaM29HM5x9p1Nv8DuTYPA==", "dependencies": { - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-menu": "2.1.6", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-controllable-state": "1.1.0" }, "peerDependencies": { "@types/react": "*", @@ -1204,54 +1123,58 @@ } } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-presence": { + "node_modules/@radix-ui/react-focus-guards": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz", - "integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0" - }, + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", + "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", "peerDependencies": { "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true - }, - "@types/react-dom": { - "optional": true } } }, - "node_modules/@radix-ui/react-direction": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", - "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", - "license": "MIT", + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz", + "integrity": "sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-callback-ref": "1.1.0" + }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true + }, + "@types/react-dom": { + "optional": true } } }, - "node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.2.tgz", - "integrity": "sha512-kEHnlhv7wUggvhuJPkyw4qspXLJOdYoAP4dO2c8ngGuXTq1w/HZp1YeVB+NQ2KbH1iEG+pvOCGYSqh9HZOz6hg==", + "node_modules/@radix-ui/react-hover-card": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.1.6.tgz", + "integrity": "sha512-E4ozl35jq0VRlrdc4dhHrNSV0JqBb4Jy73WAhBEK7JoYnQ83ED5r0Rb/XdVKw89ReAJN38N492BAPBZQ57VmqQ==", "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-escape-keydown": "1.1.0" + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.5", + "@radix-ui/react-popper": "1.2.2", + "@radix-ui/react-portal": "1.1.4", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-controllable-state": "1.1.0" }, "peerDependencies": { "@types/react": "*", @@ -1268,15 +1191,13 @@ } } }, - "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", - "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==" - }, - "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", - "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", + "node_modules/@radix-ui/react-id": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", + "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.0" + }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -1287,12 +1208,29 @@ } } }, - "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/react-primitive": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz", - "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==", + "node_modules/@radix-ui/react-menu": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.6.tgz", + "integrity": "sha512-tBBb5CXDJW3t2mo9WlO7r6GTmWV0F0uzHZVFmlRmYpiSK1CDU5IKojP1pm7oknpBOrFZx/YgBRW9oorPO2S/Lg==", "dependencies": { - "@radix-ui/react-slot": "1.1.1" + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-collection": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-dismissable-layer": "1.1.5", + "@radix-ui/react-focus-guards": "1.1.1", + "@radix-ui/react-focus-scope": "1.1.2", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-popper": "1.2.2", + "@radix-ui/react-portal": "1.1.4", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-roving-focus": "1.1.2", + "@radix-ui/react-slot": "1.1.2", + "@radix-ui/react-use-callback-ref": "1.1.0", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", @@ -1309,35 +1247,44 @@ } } }, - "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/react-slot": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz", - "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==", + "node_modules/@radix-ui/react-popper": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.2.tgz", + "integrity": "sha512-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA==", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0", + "@radix-ui/react-use-rect": "1.1.0", + "@radix-ui/react-use-size": "1.1.0", + "@radix-ui/rect": "1.1.0" }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true + }, + "@types/react-dom": { + "optional": true } } }, - "node_modules/@radix-ui/react-dropdown-menu": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.2.tgz", - "integrity": "sha512-GVZMR+eqK8/Kes0a36Qrv+i20bAPXSn8rCBTHx30w+3ECnR5o3xixAlqcVaYvLeyKUsm0aqyhWfmUcqufM8nYA==", + "node_modules/@radix-ui/react-portal": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.4.tgz", + "integrity": "sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA==", "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-menu": "2.1.2", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-controllable-state": "1.1.0" + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", @@ -1349,875 +1296,40 @@ "@types/react": { "optional": true }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-context": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", - "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-focus-guards": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", - "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-focus-scope": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz", - "integrity": "sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-hover-card": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.1.2.tgz", - "integrity": "sha512-Y5w0qGhysvmqsIy6nQxaPa6mXNKznfoGjOfBgzOjocLxr2XlSjqBMYQQL+FfyogsMuX+m8cZyQGYhJxvxUzO4w==", - "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.1", - "@radix-ui/react-popper": "1.2.0", - "@radix-ui/react-portal": "1.1.2", - "@radix-ui/react-presence": "1.1.1", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-controllable-state": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-context": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", - "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz", - "integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==", - "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-escape-keydown": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-portal": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz", - "integrity": "sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==", - "dependencies": { - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-hover-card/node_modules/@radix-ui/react-presence": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz", - "integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-id": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", - "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.2.tgz", - "integrity": "sha512-lZ0R4qR2Al6fZ4yCCZzu/ReTFrylHFxIqy7OezIpWF4bL0o9biKo0pFIvkaew3TyZ9Fy5gYVrR5zCGZBVbO1zg==", - "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-collection": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-dismissable-layer": "1.1.1", - "@radix-ui/react-focus-guards": "1.1.1", - "@radix-ui/react-focus-scope": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-popper": "1.2.0", - "@radix-ui/react-portal": "1.1.2", - "@radix-ui/react-presence": "1.1.1", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-roving-focus": "1.1.0", - "@radix-ui/react-slot": "1.1.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "aria-hidden": "^1.1.1", - "react-remove-scroll": "2.6.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-context": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", - "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz", - "integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==", - "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-escape-keydown": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-portal": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz", - "integrity": "sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==", - "dependencies": { - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-presence": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz", - "integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-popper": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz", - "integrity": "sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==", - "license": "MIT", - "dependencies": { - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-use-rect": "1.1.0", - "@radix-ui/react-use-size": "1.1.0", - "@radix-ui/rect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-portal": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.3.tgz", - "integrity": "sha512-NciRqhXnGojhT93RPyDaMPfLH3ZSl4jjIFbZQ1b/vxvZEdHsBZ49wP9w8L3HzUQwep01LcWtkUvm0OVB5JAHTw==", - "dependencies": { - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-portal/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", - "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-portal/node_modules/@radix-ui/react-primitive": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz", - "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==", - "dependencies": { - "@radix-ui/react-slot": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-portal/node_modules/@radix-ui/react-slot": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz", - "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-presence": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz", - "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-presence/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", - "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", - "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-progress": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.0.tgz", - "integrity": "sha512-aSzvnYpP725CROcxAOEBVZZSIQVQdHgBr2QQFKySsaD14u8dNT0batuXI+AAGDdAHfXH8rbnHmjYFqVJ21KkRg==", - "dependencies": { - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-primitive": "2.0.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-roving-focus": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz", - "integrity": "sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==", - "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-collection": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.3.tgz", - "integrity": "sha512-tlLwaewTfrKetiex8iW9wwME/qrYlzlH0qcgYmos7xS54MO00SiPHasLoAykg/yVrjf41GQptPPi4oXzrP+sgg==", - "dependencies": { - "@radix-ui/number": "1.1.0", - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-collection": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-dismissable-layer": "1.1.2", - "@radix-ui/react-focus-guards": "1.1.1", - "@radix-ui/react-focus-scope": "1.1.1", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-popper": "1.2.1", - "@radix-ui/react-portal": "1.1.3", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-slot": "1.1.1", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-use-previous": "1.1.0", - "@radix-ui/react-visually-hidden": "1.1.1", - "aria-hidden": "^1.1.1", - "react-remove-scroll": "2.6.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", - "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==" - }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-arrow": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.1.tgz", - "integrity": "sha512-NaVpZfmv8SKeZbn4ijN2V3jlHA9ngBG16VnIIm22nUR0Yk8KUALyBxT3KYEUnNuch9sTE8UTsS3whzBgKOL30w==", - "dependencies": { - "@radix-ui/react-primitive": "2.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-collection": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.1.tgz", - "integrity": "sha512-LwT3pSho9Dljg+wY2KN2mrrh6y3qELfftINERIzBUO9e0N+t0oMTyn3k9iv+ZqgrwGkRnLpNJrsMv9BZlt2yuA==", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-slot": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", - "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-context": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", - "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-focus-scope": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.1.tgz", - "integrity": "sha512-01omzJAYRxXdG2/he/+xy+c8a8gCydoQ1yOxnWNcRhrrBW5W+RQJ22EK1SaO8tb3WoUsuEw7mJjBozPzihDFjA==", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-use-callback-ref": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-popper": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.1.tgz", - "integrity": "sha512-3kn5Me69L+jv82EKRuQCXdYyf1DqHwD2U/sxoNgBGCB7K9TRc3bQamQ+5EPM9EvyPdli0W41sROd+ZU1dTCztw==", - "dependencies": { - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-use-rect": "1.1.0", - "@radix-ui/react-use-size": "1.1.0", - "@radix-ui/rect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-primitive": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz", - "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==", - "dependencies": { - "@radix-ui/react-slot": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz", - "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", - "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-toast": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.3.tgz", - "integrity": "sha512-oB8irs7CGAml6zWbum7MNySTH/sR7PM1ZQyLV8reO946u73sU83yZUKijrMLNbm4hTOrJY4tE8Oa/XUKrOr2Wg==", - "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-collection": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.2", - "@radix-ui/react-portal": "1.1.3", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-visually-hidden": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-toast/node_modules/@radix-ui/primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", - "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==" - }, - "node_modules/@radix-ui/react-toast/node_modules/@radix-ui/react-collection": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.1.tgz", - "integrity": "sha512-LwT3pSho9Dljg+wY2KN2mrrh6y3qELfftINERIzBUO9e0N+t0oMTyn3k9iv+ZqgrwGkRnLpNJrsMv9BZlt2yuA==", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-slot": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-toast/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", - "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { + "@types/react-dom": { "optional": true } } }, - "node_modules/@radix-ui/react-toast/node_modules/@radix-ui/react-context": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", - "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "node_modules/@radix-ui/react-presence": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz", + "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true + }, + "@types/react-dom": { + "optional": true } } }, - "node_modules/@radix-ui/react-toast/node_modules/@radix-ui/react-primitive": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz", - "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==", + "node_modules/@radix-ui/react-primitive": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz", + "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==", "dependencies": { - "@radix-ui/react-slot": "1.1.1" + "@radix-ui/react-slot": "1.1.2" }, "peerDependencies": { "@types/react": "*", @@ -2234,40 +1346,43 @@ } } }, - "node_modules/@radix-ui/react-toast/node_modules/@radix-ui/react-slot": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz", - "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==", + "node_modules/@radix-ui/react-progress": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.2.tgz", + "integrity": "sha512-u1IgJFQ4zNAUTjGdDL5dcl/U8ntOR6jsnhxKb5RKp5Ozwl88xKR9EqRZOe/Mk8tnx0x5tNUe2F+MzsyjqMg0MA==", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-primitive": "2.0.2" }, "peerDependencies": { "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { "optional": true + }, + "@types/react-dom": { + "optional": true } } }, - "node_modules/@radix-ui/react-tooltip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.5.tgz", - "integrity": "sha512-IucoQPcK5nwUuztaxBQvudvYwH58wtRcJlv1qvaMSyIbL9dEBfFN0vRf/D8xDbu6HmAJLlNGty4z8Na+vIqe9Q==", + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.2.tgz", + "integrity": "sha512-zgMQWkNO169GtGqRvYrzb0Zf8NhMHS2DuEB/TiEmVnpr5OqPU3i8lfbxaAmC2J/KYuIQxyoQQ6DxepyXp61/xw==", "dependencies": { "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-collection": "1.1.2", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.2", + "@radix-ui/react-direction": "1.1.0", "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-popper": "1.2.1", - "@radix-ui/react-portal": "1.1.3", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.1", - "@radix-ui/react-slot": "1.1.1", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-visually-hidden": "1.1.1" + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0" }, "peerDependencies": { "@types/react": "*", @@ -2284,17 +1399,32 @@ } } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", - "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==" - }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-arrow": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.1.tgz", - "integrity": "sha512-NaVpZfmv8SKeZbn4ijN2V3jlHA9ngBG16VnIIm22nUR0Yk8KUALyBxT3KYEUnNuch9sTE8UTsS3whzBgKOL30w==", + "node_modules/@radix-ui/react-select": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.6.tgz", + "integrity": "sha512-T6ajELxRvTuAMWH0YmRJ1qez+x4/7Nq7QIx7zJ0VK3qaEWdnWpNbEDnmWldG1zBDwqrLy5aLMUWcoGirVj5kMg==", "dependencies": { - "@radix-ui/react-primitive": "2.0.1" + "@radix-ui/number": "1.1.0", + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-collection": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-dismissable-layer": "1.1.5", + "@radix-ui/react-focus-guards": "1.1.1", + "@radix-ui/react-focus-scope": "1.1.2", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-popper": "1.2.2", + "@radix-ui/react-portal": "1.1.4", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-slot": "1.1.2", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0", + "@radix-ui/react-use-previous": "1.1.0", + "@radix-ui/react-visually-hidden": "1.1.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", @@ -2311,24 +1441,13 @@ } } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", - "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "node_modules/@radix-ui/react-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", + "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-context": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", - "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -2339,21 +1458,23 @@ } } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-popper": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.1.tgz", - "integrity": "sha512-3kn5Me69L+jv82EKRuQCXdYyf1DqHwD2U/sxoNgBGCB7K9TRc3bQamQ+5EPM9EvyPdli0W41sROd+ZU1dTCztw==", + "node_modules/@radix-ui/react-toast": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.6.tgz", + "integrity": "sha512-gN4dpuIVKEgpLn1z5FhzT9mYRUitbfZq9XqN/7kkBMUgFTzTG8x/KszWJugJXHcwxckY8xcKDZPz7kG3o6DsUA==", "dependencies": { - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.1", + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-collection": "1.1.2", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-dismissable-layer": "1.1.5", + "@radix-ui/react-portal": "1.1.4", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0", "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-use-rect": "1.1.0", - "@radix-ui/react-use-size": "1.1.0", - "@radix-ui/rect": "1.1.0" + "@radix-ui/react-visually-hidden": "1.1.2" }, "peerDependencies": { "@types/react": "*", @@ -2370,12 +1491,23 @@ } } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-primitive": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz", - "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==", + "node_modules/@radix-ui/react-tooltip": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.8.tgz", + "integrity": "sha512-YAA2cu48EkJZdAMHC0dqo9kialOcRStbtiY4nJPaht7Ptrhcvpo+eDChaM6BIs8kL6a8Z5l5poiqLnXcNduOkA==", "dependencies": { - "@radix-ui/react-slot": "1.1.1" + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.5", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-popper": "1.2.2", + "@radix-ui/react-portal": "1.1.4", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-slot": "1.1.2", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-visually-hidden": "1.1.2" }, "peerDependencies": { "@types/react": "*", @@ -2392,28 +1524,10 @@ } } }, - "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz", - "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/@radix-ui/react-use-callback-ref": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", - "license": "MIT", "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -2428,7 +1542,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", - "license": "MIT", "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.0" }, @@ -2446,7 +1559,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz", "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==", - "license": "MIT", "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.0" }, @@ -2464,7 +1576,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", - "license": "MIT", "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -2479,7 +1590,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz", "integrity": "sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==", - "license": "MIT", "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -2494,7 +1604,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz", "integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==", - "license": "MIT", "dependencies": { "@radix-ui/rect": "1.1.0" }, @@ -2512,7 +1621,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", - "license": "MIT", "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, @@ -2527,47 +1635,11 @@ } }, "node_modules/@radix-ui/react-visually-hidden": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.1.tgz", - "integrity": "sha512-vVfA2IZ9q/J+gEamvj761Oq1FpWgCDaNOOIfbPVp2MVPLEomUr5+Vf7kJGwQ24YxZSlQVar7Bes8kyTo5Dshpg==", - "dependencies": { - "@radix-ui/react-primitive": "2.0.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", - "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-primitive": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz", - "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.2.tgz", + "integrity": "sha512-1SzA4ns2M1aRlvxErqhLHsBHoS5eI5UUcI2awAMgGUp4LoaoWOKYmvqDY2s/tltuPkh3Yk77YF/r3IRj+Amx4Q==", "dependencies": { - "@radix-ui/react-slot": "1.1.1" + "@radix-ui/react-primitive": "2.0.2" }, "peerDependencies": { "@types/react": "*", @@ -2584,28 +1656,10 @@ } } }, - "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-slot": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz", - "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/@radix-ui/rect": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz", - "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==", - "license": "MIT" + "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==" }, "node_modules/@rtsao/scc": { "version": "1.1.0", @@ -2614,11 +1668,10 @@ "dev": true }, "node_modules/@rushstack/eslint-patch": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz", - "integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==", - "dev": true, - "license": "MIT" + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.5.tgz", + "integrity": "sha512-kkKUDVlII2DQiKy7UstOR1ErJP8kUKAQ4oa+SQtM0K+lPdmmjj0YnnxBgtTVYH7mUKtbsxeFC9y0AmK7Yb78/A==", + "dev": true }, "node_modules/@swc/counter": { "version": "0.1.3", @@ -2642,8 +1695,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@types/hast": { "version": "2.3.10", @@ -2657,53 +1709,49 @@ "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@types/lodash": { - "version": "4.17.14", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.14.tgz", - "integrity": "sha512-jsxagdikDiDBeIRaPYtArcT8my4tN1og7MtMRquFT3XNA6axxyHDRUemqDz/taRDdOUn0GnGHRCuff4q48sW9A==" + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==" }, "node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "version": "22.13.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", + "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", "dev": true, "dependencies": { "undici-types": "~6.20.0" } }, "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "license": "MIT" + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==" }, "node_modules/@types/react": { - "version": "18.3.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", - "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", - "license": "MIT", + "version": "18.3.18", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz", + "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==", + "version": "18.3.5", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.5.tgz", + "integrity": "sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==", "devOptional": true, - "dependencies": { - "@types/react": "*" + "peerDependencies": { + "@types/react": "^18.0.0" } }, "node_modules/@types/react-gtm-module": { @@ -2726,20 +1774,20 @@ "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.13.0.tgz", - "integrity": "sha512-nQtBLiZYMUPkclSeC3id+x4uVd1SGtHuElTxL++SfP47jR0zfkZBJHc+gL4qPsgTuypz0k8Y2GheaDYn6Gy3rg==", + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.24.0.tgz", + "integrity": "sha512-aFcXEJJCI4gUdXgoo/j9udUYIHgF23MFkg09LFz2dzEmU0+1Plk4rQWv/IYKvPHAtlkkGoB3m5e6oUp+JPsNaQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.13.0", - "@typescript-eslint/type-utils": "8.13.0", - "@typescript-eslint/utils": "8.13.0", - "@typescript-eslint/visitor-keys": "8.13.0", + "@typescript-eslint/scope-manager": "8.24.0", + "@typescript-eslint/type-utils": "8.24.0", + "@typescript-eslint/utils": "8.24.0", + "@typescript-eslint/visitor-keys": "8.24.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2750,24 +1798,20 @@ }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.13.0.tgz", - "integrity": "sha512-w0xp+xGg8u/nONcGw1UXAr6cjCPU1w0XVyBs6Zqaj5eLmxkKQAByTdV/uGgNN5tVvN/kKpoQlP2cL7R+ajZZIQ==", + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.24.0.tgz", + "integrity": "sha512-MFDaO9CYiard9j9VepMNa9MTcqVvSny2N4hkY6roquzj8pdCBRENhErrteaQuu7Yjn1ppk0v1/ZF9CG3KIlrTA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.13.0", - "@typescript-eslint/types": "8.13.0", - "@typescript-eslint/typescript-estree": "8.13.0", - "@typescript-eslint/visitor-keys": "8.13.0", + "@typescript-eslint/scope-manager": "8.24.0", + "@typescript-eslint/types": "8.24.0", + "@typescript-eslint/typescript-estree": "8.24.0", + "@typescript-eslint/visitor-keys": "8.24.0", "debug": "^4.3.4" }, "engines": { @@ -2778,22 +1822,18 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.13.0.tgz", - "integrity": "sha512-XsGWww0odcUT0gJoBZ1DeulY1+jkaHUciUq4jKNv4cpInbvvrtDoyBH9rE/n2V29wQJPk8iCH1wipra9BhmiMA==", + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.24.0.tgz", + "integrity": "sha512-HZIX0UByphEtdVBKaQBgTDdn9z16l4aTUz8e8zPQnyxwHBtf5vtl1L+OhH+m1FGV9DrRmoDuYKqzVrvWDcDozw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.13.0", - "@typescript-eslint/visitor-keys": "8.13.0" + "@typescript-eslint/types": "8.24.0", + "@typescript-eslint/visitor-keys": "8.24.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2804,15 +1844,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.13.0.tgz", - "integrity": "sha512-Rqnn6xXTR316fP4D2pohZenJnp+NwQ1mo7/JM+J1LWZENSLkJI8ID8QNtlvFeb0HnFSK94D6q0cnMX6SbE5/vA==", + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.24.0.tgz", + "integrity": "sha512-8fitJudrnY8aq0F1wMiPM1UUgiXQRJ5i8tFjq9kGfRajU+dbPyOuHbl0qRopLEidy0MwqgTHDt6CnSeXanNIwA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.13.0", - "@typescript-eslint/utils": "8.13.0", + "@typescript-eslint/typescript-estree": "8.24.0", + "@typescript-eslint/utils": "8.24.0", "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2821,16 +1861,15 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.13.0.tgz", - "integrity": "sha512-4cyFErJetFLckcThRUFdReWJjVsPCqyBlJTi6IDEpc1GWCIIZRFxVppjWLIMcQhNGhdWJJRYFHpHoDWvMlDzng==", + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.24.0.tgz", + "integrity": "sha512-VacJCBTyje7HGAw7xp11q439A+zeGG0p0/p2zsZwpnMzjPB5WteaWqt4g2iysgGFafrqvyLWqq6ZPZAOCoefCw==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2841,19 +1880,19 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.13.0.tgz", - "integrity": "sha512-v7SCIGmVsRK2Cy/LTLGN22uea6SaUIlpBcO/gnMGT/7zPtxp90bphcGf4fyrCQl3ZtiBKqVTG32hb668oIYy1g==", + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.24.0.tgz", + "integrity": "sha512-ITjYcP0+8kbsvT9bysygfIfb+hBj6koDsu37JZG7xrCiy3fPJyNmfVtaGsgTUSEuTzcvME5YI5uyL5LD1EV5ZQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.13.0", - "@typescript-eslint/visitor-keys": "8.13.0", + "@typescript-eslint/types": "8.24.0", + "@typescript-eslint/visitor-keys": "8.24.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2862,10 +1901,8 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { @@ -2877,6 +1914,34 @@ "balanced-match": "^1.0.0" } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -2893,15 +1958,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.13.0.tgz", - "integrity": "sha512-A1EeYOND6Uv250nybnLZapeXpYMl8tkzYUxqmoKAWnI4sei3ihf2XdZVd+vVOmHGcp3t+P7yRrNsyyiXTvShFQ==", + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.24.0.tgz", + "integrity": "sha512-07rLuUBElvvEb1ICnafYWr4hk8/U7X9RDCOqd9JcAMtjh/9oRmcfN4yGzbPVirgMR0+HLVHehmu19CWeh7fsmQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.13.0", - "@typescript-eslint/types": "8.13.0", - "@typescript-eslint/typescript-estree": "8.13.0" + "@typescript-eslint/scope-manager": "8.24.0", + "@typescript-eslint/types": "8.24.0", + "@typescript-eslint/typescript-estree": "8.24.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2911,15 +1976,26 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.13.0.tgz", - "integrity": "sha512-7N/+lztJqH4Mrf0lb10R/CbI1EaAMMGyF5y0oJvFoAhafwgiRA7TXyd8TFn8FC8k5y2dTsYogg238qavRGNnlw==", + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.24.0.tgz", + "integrity": "sha512-kArLq83QxGLbuHrTMoOEWO+l2MwsNS2TGISEdx8xgqpkbytB07XmlQyQdNDrCc1ecSqx0cnmhGvpX+VBwqqSkg==", "dev": true, - "license": "ISC" + "dependencies": { + "@typescript-eslint/types": "8.24.0", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } }, "node_modules/accessor-fn": { "version": "1.5.1", @@ -2934,7 +2010,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, - "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -2947,7 +2022,6 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -2957,7 +2031,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2970,19 +2043,20 @@ } }, "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -2996,14 +2070,12 @@ "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "license": "MIT" + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -3015,21 +2087,18 @@ "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "license": "MIT" + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" + "dev": true }, "node_modules/aria-hidden": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", - "license": "MIT", "dependencies": { "tslib": "^2.0.0" }, @@ -3047,13 +2116,13 @@ } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" }, "engines": { "node": ">= 0.4" @@ -3067,7 +2136,6 @@ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -3108,7 +2176,6 @@ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -3125,16 +2192,15 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3144,16 +2210,15 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3205,6 +2270,15 @@ "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", "dev": true }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/autoprefixer": { "version": "10.4.20", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", @@ -3246,7 +2320,6 @@ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, - "license": "MIT", "dependencies": { "possible-typed-array-names": "^1.0.0" }, @@ -3278,8 +2351,7 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base64-arraybuffer": { "version": "1.0.2", @@ -3302,7 +2374,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "license": "MIT", "engines": { "node": ">=8" }, @@ -3315,7 +2386,6 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3325,7 +2395,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -3334,9 +2403,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", - "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "funding": [ { "type": "opencollective", @@ -3352,9 +2421,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001669", - "electron-to-chromium": "^1.5.41", - "node-releases": "^2.0.18", + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" }, "bin": { @@ -3427,7 +2496,6 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } @@ -3436,15 +2504,14 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001680", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001680.tgz", - "integrity": "sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==", + "version": "1.0.30001699", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001699.tgz", + "integrity": "sha512-b+uH5BakXZ9Do9iK+CkDmctUSEqZl+SP056vc5usa0PL+ev5OHw003rZXcnjNDv3L8P5j6rwT6C0BPKSikW08w==", "funding": [ { "type": "opencollective", @@ -3481,7 +2548,6 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -3524,7 +2590,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -3548,7 +2613,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -3576,7 +2640,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", "engines": { "node": ">=6" } @@ -3597,7 +2660,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -3608,8 +2670,7 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/color-string": { "version": "1.9.1", @@ -3633,7 +2694,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "license": "MIT", "engines": { "node": ">= 6" } @@ -3642,14 +2702,12 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/cross-spawn": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.5.tgz", - "integrity": "sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==", - "license": "MIT", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -3671,7 +2729,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "license": "MIT", "bin": { "cssesc": "bin/cssesc" }, @@ -3682,8 +2739,7 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "license": "MIT" + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/d3-array": { "version": "3.2.4", @@ -3772,9 +2828,9 @@ } }, "node_modules/d3-octree": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-octree/-/d3-octree-1.0.2.tgz", - "integrity": "sha512-Qxg4oirJrNXauiuC94uKMbgxwnhdda9xRLl9ihq45srlJ4Ga3CSgqGcAL8iW7N5CIv4Oz8x3E734ulxyvHPvwA==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-octree/-/d3-octree-1.1.0.tgz", + "integrity": "sha512-F8gPlqpP+HwRPMO/8uOu5wjH110+6q4cgJvgJT6vlpy3BEaDIKlTZrgHKZSp/i1InRpVfh4puY/kvL6MxK930A==" }, "node_modules/d3-quadtree": { "version": "3.0.1", @@ -3889,15 +2945,14 @@ "dev": true }, "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3907,31 +2962,29 @@ } }, "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/inspect-js" } }, "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" }, @@ -3943,13 +2996,12 @@ } }, "node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, - "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -3964,15 +3016,13 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, - "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -3990,7 +3040,6 @@ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, - "license": "MIT", "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -4015,20 +3064,17 @@ "node_modules/detect-node-es": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", - "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", - "license": "MIT" + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "license": "Apache-2.0" + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "license": "MIT" + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" }, "node_modules/doctrine": { "version": "2.1.0", @@ -4043,12 +3089,12 @@ } }, "node_modules/dunder-proto": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.0.tgz", - "integrity": "sha512-9+Sj30DIu+4KvHqMfLUGLFYL2PkURSYMVXJyXe92nFRvlYq5hBjLEhblKB+vkd/WVlUYMWigiY07T91Fkk0+4A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "dev": true, "dependencies": { - "call-bind-apply-helpers": "^1.0.0", + "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" }, @@ -4059,26 +3105,23 @@ "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "license": "MIT" + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "node_modules/electron-to-chromium": { - "version": "1.5.63", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.63.tgz", - "integrity": "sha512-ddeXKuY9BHo/mw145axlyWjlJ1UBt4WK3AlvkT7W2AbqfRQoacVoRUCF6wL3uIx/8wT9oLKXzI+rFqHHscByaA==" + "version": "1.5.97", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.97.tgz", + "integrity": "sha512-HKLtaH02augM7ZOdYRuO19rWDeY+QSJ1VxnXFa/XDFLf07HvM90pALIJFgrO+UVaajI3+aJMMpojoUTLZyQ7JQ==" }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "license": "MIT" + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "node_modules/enhanced-resolve": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "version": "5.18.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", + "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -4088,27 +3131,28 @@ } }, "node_modules/es-abstract": { - "version": "1.23.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.6.tgz", - "integrity": "sha512-Ifco6n3yj2tMZDWNLyloZrytt9lqqlwvS83P3HtaETR0NUOYnIULGGHpktqYGObGy+8wc1okO25p8TjemhImvA==", + "version": "1.23.9", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", + "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.1", + "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.3", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", + "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.7", - "get-intrinsic": "^1.2.6", - "get-symbol-description": "^1.0.2", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.0", + "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", @@ -4116,31 +3160,33 @@ "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.4", + "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", - "is-shared-array-buffer": "^1.0.3", + "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", - "is-typed-array": "^1.1.13", + "is-typed-array": "^1.1.15", "is-weakref": "^1.1.0", - "math-intrinsics": "^1.0.0", + "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.3", "object-keys": "^1.1.1", - "object.assign": "^4.1.5", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.3", "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.3", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.16" + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.18" }, "engines": { "node": ">= 0.4" @@ -4163,43 +3209,42 @@ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/es-iterator-helpers": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.0.tgz", - "integrity": "sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", + "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", + "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", + "get-intrinsic": "^1.2.6", "globalthis": "^1.0.4", - "gopd": "^1.0.1", + "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.3", - "safe-array-concat": "^1.1.2" + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.4", + "safe-array-concat": "^1.1.3" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "dev": true, - "license": "MIT", "dependencies": { "es-errors": "^1.3.0" }, @@ -4208,28 +3253,30 @@ } }, "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, - "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.4", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, - "license": "MIT", "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/es-to-primitive": { @@ -4262,7 +3309,6 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -4271,19 +3317,18 @@ } }, "node_modules/eslint": { - "version": "9.15.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.15.0.tgz", - "integrity": "sha512-7CrWySmIibCgT1Os28lUU6upBshZ+GxybLOrmRzi08kS8MBuO8QA7pXEgYgY5W8vK3e74xv0lpjo9DbaGU9Rkw==", + "version": "9.20.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.20.1.tgz", + "integrity": "sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.0", - "@eslint/core": "^0.9.0", + "@eslint/core": "^0.11.0", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.15.0", - "@eslint/plugin-kit": "^0.2.3", + "@eslint/js": "9.20.0", + "@eslint/plugin-kit": "^0.2.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.1", @@ -4291,7 +3336,7 @@ "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.5", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.2.0", @@ -4331,12 +3376,12 @@ } }, "node_modules/eslint-config-next": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.1.2.tgz", - "integrity": "sha512-PrMm1/4zWSJ689wd/ypWIR5ZF1uvmp3EkgpgBV1Yu6PhEobBjXMGgT8bVNelwl17LXojO8D5ePFRiI4qXjsPRA==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.1.7.tgz", + "integrity": "sha512-zXoMnYUIy3XHaAoOhrcYkT9UQWvXqWju2K7NNsmb5wd/7XESDwof61eUdW4QhERr3eJ9Ko/vnXqIrj8kk/drYw==", "dev": true, "dependencies": { - "@next/eslint-plugin-next": "15.1.2", + "@next/eslint-plugin-next": "15.1.7", "@rushstack/eslint-patch": "^1.10.3", "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", @@ -4362,7 +3407,6 @@ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, - "license": "MIT", "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", @@ -4374,25 +3418,24 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, "node_modules/eslint-import-resolver-typescript": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", - "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.7.0.tgz", + "integrity": "sha512-Vrwyi8HHxY97K5ebydMtffsWAn1SCR9eol49eCd5fJS4O1WV7PaAjbcjmbfJJSMz/t4Mal212Uz/fQZrOB8mow==", "dev": true, - "license": "ISC", "dependencies": { - "debug": "^4.3.4", - "enhanced-resolve": "^5.12.0", - "eslint-module-utils": "^2.7.4", - "fast-glob": "^3.3.1", - "get-tsconfig": "^4.5.0", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3" + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.3.7", + "enhanced-resolve": "^5.15.0", + "fast-glob": "^3.3.2", + "get-tsconfig": "^4.7.5", + "is-bun-module": "^1.0.2", + "is-glob": "^4.0.3", + "stable-hash": "^0.0.4" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -4402,7 +3445,44 @@ }, "peerDependencies": { "eslint": "*", - "eslint-plugin-import": "*" + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, "node_modules/eslint-module-utils": { @@ -4427,7 +3507,6 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "license": "MIT", "dependencies": { "ms": "^2.1.1" } @@ -4470,7 +3549,6 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "license": "MIT", "dependencies": { "ms": "^2.1.1" } @@ -4480,7 +3558,6 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -4515,28 +3592,28 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.37.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", - "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", + "version": "7.37.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz", + "integrity": "sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==", "dev": true, "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.2", + "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.1.0", + "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.8", "object.fromentries": "^2.0.8", - "object.values": "^1.2.0", + "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.11", + "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "engines": { @@ -4547,9 +3624,9 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0.tgz", - "integrity": "sha512-hIOwI+5hYGpJEc4uPRmz2ulCjAGD/N13Lukkh8cLV0i2IRk/bdZDYjgLVHj+U9Z704kLIdIO6iueGvxNur0sgw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.1.0.tgz", + "integrity": "sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw==", "dev": true, "engines": { "node": ">=10" @@ -4589,7 +3666,6 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -4602,24 +3678,10 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, - "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -4632,7 +3694,6 @@ "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", @@ -4645,25 +3706,11 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/esquery": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -4676,7 +3723,6 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -4689,7 +3735,6 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -4699,7 +3744,6 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -4708,14 +3752,13 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "license": "MIT", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -4731,7 +3774,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "license": "ISC", + "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -4743,21 +3786,18 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "license": "ISC", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", + "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", "dependencies": { "reusify": "^1.0.4" } @@ -4779,7 +3819,6 @@ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, - "license": "MIT", "dependencies": { "flat-cache": "^4.0.0" }, @@ -4791,7 +3830,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -4804,7 +3842,6 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, - "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -4821,7 +3858,6 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, - "license": "MIT", "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" @@ -4831,26 +3867,43 @@ } }, "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true, - "license": "ISC" + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "dev": true + }, + "node_modules/float-tooltip": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/float-tooltip/-/float-tooltip-1.7.3.tgz", + "integrity": "sha512-k7/1nX3J5POXBF+xXt1M33BpBpZgJn+GkFu+u89NuULOZmBCbWywNvS1EmdmADooAMz1MoONMiKvlGZ1kfTrqA==", + "dependencies": { + "d3-selection": "2 - 3", + "kapsule": "^1.16", + "preact": "10" + }, + "engines": { + "node": ">=12" + } }, "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, - "license": "MIT", "dependencies": { - "is-callable": "^1.1.3" + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/force-graph": { - "version": "1.47.1", - "resolved": "https://registry.npmjs.org/force-graph/-/force-graph-1.47.1.tgz", - "integrity": "sha512-NF0prpR8tNGq7oCE/aFImT/6/3wSk585bcp39UAj6SNSPjvKbX6ktCH6cZnjfsnPNx/DYj1rn+cvvjH814HCFA==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/force-graph/-/force-graph-1.49.0.tgz", + "integrity": "sha512-S8ODRE6eVtHtkIPCRu9Zj03uL/l8EpwKIZnIzLZO6aiZIMQLI8JguEeT3uCozT9kB2nLXem0xCiA7Pnk38Yy7g==", "dependencies": { "@tweenjs/tween.js": "18 - 25", "accessor-fn": "1", @@ -4863,6 +3916,7 @@ "d3-scale-chromatic": "1 - 3", "d3-selection": "2 - 3", "d3-zoom": "2 - 3", + "float-tooltip": "^1.6", "index-array-by": "1", "kapsule": "^1.16", "lodash-es": "4" @@ -4875,7 +3929,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", - "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -4924,18 +3977,18 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/function.prototype.name": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.7.tgz", - "integrity": "sha512-2g4x+HqTJKM9zcJqBSpjoRmdcPFtJM60J3xJisTQSXBWka5XqyBN/2tNUgma1mztTXyDuUsEtYe5qcs7xYzYQA==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, "dependencies": { "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", "functions-have-names": "^1.2.3", "hasown": "^2.0.2", @@ -4953,27 +4006,26 @@ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, - "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-intrinsic": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", - "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", "dev": true, "dependencies": { "call-bind-apply-helpers": "^1.0.1", - "dunder-proto": "^1.0.0", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", + "get-proto": "^1.0.0", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", - "math-intrinsics": "^1.0.0" + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -4986,21 +4038,32 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", - "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -5010,11 +4073,10 @@ } }, "node_modules/get-tsconfig": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.6.tgz", - "integrity": "sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", + "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", "dev": true, - "license": "MIT", "dependencies": { "resolve-pkg-maps": "^1.0.0" }, @@ -5023,23 +4085,20 @@ } }, "node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "license": "ISC", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -5048,7 +4107,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -5060,7 +4118,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -5069,7 +4126,6 @@ "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -5085,7 +4141,6 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=18" }, @@ -5098,7 +4153,6 @@ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, - "license": "MIT", "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" @@ -5126,22 +4180,22 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" + "dev": true }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true, - "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5151,7 +4205,6 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -5161,7 +4214,6 @@ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, - "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" }, @@ -5201,7 +4253,6 @@ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, - "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" }, @@ -5216,7 +4267,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -5275,21 +4325,19 @@ } }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, - "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, - "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -5306,7 +4354,6 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.19" } @@ -5341,15 +4388,6 @@ "node": ">=12" } }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.0.0" - } - }, "node_modules/is-alphabetical": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", @@ -5373,13 +4411,14 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -5394,12 +4433,16 @@ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -5427,7 +4470,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -5436,12 +4478,12 @@ } }, "node_modules/is-boolean-object": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz", - "integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "dev": true, "dependencies": { - "call-bound": "^1.0.2", + "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" }, "engines": { @@ -5451,12 +4493,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-bun-module": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.3.0.tgz", + "integrity": "sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==", + "dev": true, + "dependencies": { + "semver": "^7.6.3" + } + }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -5465,9 +4515,9 @@ } }, "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dependencies": { "hasown": "^2.0.2" }, @@ -5524,18 +4574,17 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/is-finalizationregistry": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.0.tgz", - "integrity": "sha512-qfMdqbAQEwBw78ZyReKnlA8ezmPdb9BemzIIip/JkjaZUhitfXDkkr+3QTboW0JrSXT1QWyYShpvnNHGZ4c4yA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", "dev": true, "dependencies": { - "call-bind": "^1.0.7" + "call-bound": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -5548,18 +4597,20 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -5572,7 +4623,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -5601,24 +4651,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -5670,12 +4706,12 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, "dependencies": { - "call-bind": "^1.0.7" + "call-bound": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -5718,13 +4754,12 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, - "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.14" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -5746,12 +4781,12 @@ } }, "node_modules/is-weakref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz", - "integrity": "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, "dependencies": { - "call-bound": "^1.0.2" + "call-bound": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -5761,13 +4796,13 @@ } }, "node_modules/is-weakset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", - "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -5780,26 +4815,24 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "license": "ISC" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/iterator.prototype": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.4.tgz", - "integrity": "sha512-x4WH0BWmrMmg4oHHl+duwubhrvczGlyuGAZu3nvrf0UXOfPu8IhZObFEr7DE/iv01YgVZrsOiRcqw2srkKEDIA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", "dev": true, "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", "has-symbols": "^1.1.0", - "reflect.getprototypeof": "^1.0.8", "set-function-name": "^2.0.2" }, "engines": { @@ -5807,16 +4840,12 @@ } }, "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "license": "BlueOak-1.0.0", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dependencies": { "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=14" - }, "funding": { "url": "https://github.com/sponsors/isaacs" }, @@ -5833,10 +4862,9 @@ } }, "node_modules/jiti": { - "version": "1.21.6", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", - "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", - "license": "MIT", + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "bin": { "jiti": "bin/jiti.js" } @@ -5844,15 +4872,13 @@ "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "license": "MIT" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -5864,29 +4890,25 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/json5": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, - "license": "MIT", "dependencies": { "minimist": "^1.2.0" }, @@ -5899,7 +4921,6 @@ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", "dev": true, - "license": "MIT", "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", @@ -5926,7 +4947,6 @@ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, - "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -5954,7 +4974,6 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, - "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -5964,26 +4983,26 @@ } }, "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "license": "MIT", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", "engines": { - "node": ">=10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "license": "MIT" + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, - "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -6003,14 +5022,12 @@ "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -6034,8 +5051,7 @@ "node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" }, "node_modules/lucide-react": { "version": "0.441.0", @@ -6046,9 +5062,9 @@ } }, "node_modules/math-intrinsics": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.0.0.tgz", - "integrity": "sha512-4MqMiKP90ybymYvsut0CH2g4XWbfLtmlCkXmtmdcDCxNB+mQcu1w/1+L/VD7vi/PSv7X2JYV7SCcR+jiPXnQtA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "dev": true, "engines": { "node": ">= 0.4" @@ -6058,7 +5074,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "license": "MIT", "engines": { "node": ">= 8" } @@ -6080,7 +5095,6 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -6093,7 +5107,6 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, - "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -6102,23 +5115,20 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true, - "license": "MIT" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "license": "MIT", "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", @@ -6126,16 +5136,15 @@ } }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -6147,15 +5156,14 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/next": { - "version": "15.1.2", - "resolved": "https://registry.npmjs.org/next/-/next-15.1.2.tgz", - "integrity": "sha512-nLJDV7peNy+0oHlmY2JZjzMfJ8Aj0/dd3jCwSZS8ZiO5nkQfcZRqDrRN3U5rJtqVTQneIOGZzb6LCNrk7trMCQ==", + "version": "15.1.7", + "resolved": "https://registry.npmjs.org/next/-/next-15.1.7.tgz", + "integrity": "sha512-GNeINPGS9c6OZKCvKypbL8GTsT5GhWPp4DM0fzkXJuXMilOO2EeFxuAY6JZbtk6XIl6Ws10ag3xRINDjSO5+wg==", "dependencies": { - "@next/env": "15.1.2", + "@next/env": "15.1.7", "@swc/counter": "0.1.3", "@swc/helpers": "0.5.15", "busboy": "1.6.0", @@ -6170,14 +5178,14 @@ "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "15.1.2", - "@next/swc-darwin-x64": "15.1.2", - "@next/swc-linux-arm64-gnu": "15.1.2", - "@next/swc-linux-arm64-musl": "15.1.2", - "@next/swc-linux-x64-gnu": "15.1.2", - "@next/swc-linux-x64-musl": "15.1.2", - "@next/swc-win32-arm64-msvc": "15.1.2", - "@next/swc-win32-x64-msvc": "15.1.2", + "@next/swc-darwin-arm64": "15.1.7", + "@next/swc-darwin-x64": "15.1.7", + "@next/swc-linux-arm64-gnu": "15.1.7", + "@next/swc-linux-arm64-musl": "15.1.7", + "@next/swc-linux-x64-gnu": "15.1.7", + "@next/swc-linux-x64-musl": "15.1.7", + "@next/swc-win32-arm64-msvc": "15.1.7", + "@next/swc-win32-x64-msvc": "15.1.7", "sharp": "^0.33.5" }, "peerDependencies": { @@ -6231,15 +5239,14 @@ } }, "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==" }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -6256,7 +5263,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -6265,15 +5271,14 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/object-inspect": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", - "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, "engines": { "node": ">= 0.4" @@ -6287,21 +5292,21 @@ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", "object-keys": "^1.1.1" }, "engines": { @@ -6330,7 +5335,6 @@ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -6349,7 +5353,6 @@ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -6360,13 +5363,13 @@ } }, "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, @@ -6382,7 +5385,6 @@ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, - "license": "MIT", "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -6395,12 +5397,28 @@ "node": ">= 0.8.0" } }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, - "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -6416,7 +5434,6 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, - "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -6427,12 +5444,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, - "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -6462,7 +5483,6 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -6471,7 +5491,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "license": "MIT", "engines": { "node": ">=8" } @@ -6479,14 +5498,12 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "license": "MIT" + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-scurry": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -6507,7 +5524,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "license": "MIT", "engines": { "node": ">=8.6" }, @@ -6515,21 +5531,28 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/pirates": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/playwright": { - "version": "1.49.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.1.tgz", - "integrity": "sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==", + "version": "1.50.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.50.1.tgz", + "integrity": "sha512-G8rwsOQJ63XG6BbKj2w5rHeavFjy5zynBA9zsJMMtBoe/Uf757oG12NXz6e6OirF7RCrTVAKFXbLmn1RbL7Qaw==", "dependencies": { - "playwright-core": "1.49.1" + "playwright-core": "1.50.1" }, "bin": { "playwright": "cli.js" @@ -6542,9 +5565,9 @@ } }, "node_modules/playwright-core": { - "version": "1.49.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.1.tgz", - "integrity": "sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==", + "version": "1.50.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.50.1.tgz", + "integrity": "sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ==", "bin": { "playwright-core": "cli.js" }, @@ -6553,19 +5576,18 @@ } }, "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz", + "integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==", "funding": [ { "type": "opencollective", @@ -6581,7 +5603,7 @@ } ], "dependencies": { - "nanoid": "^3.3.7", + "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -6593,7 +5615,6 @@ "version": "15.1.0", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "license": "MIT", "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", @@ -6610,7 +5631,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "license": "MIT", "dependencies": { "camelcase-css": "^2.0.1" }, @@ -6639,7 +5659,6 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { "lilconfig": "^3.0.0", "yaml": "^2.3.4" @@ -6660,18 +5679,6 @@ } } }, - "node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", - "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", - "license": "MIT", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, "node_modules/postcss-nested": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", @@ -6686,7 +5693,6 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { "postcss-selector-parser": "^6.1.1" }, @@ -6712,15 +5718,22 @@ "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "license": "MIT" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/preact": { + "version": "10.25.4", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.25.4.tgz", + "integrity": "sha512-jLdZDb+Q+odkHJ+MpW/9U5cODzqnB+fy2EiHSZES7ldV5LK7yjlVzTp7R8Xy6W6y75kfK8iWYtFVH7lvjwrCMA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.8.0" } @@ -6737,7 +5750,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -6761,7 +5773,6 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } @@ -6783,14 +5794,12 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "MIT" + ] }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" }, @@ -6813,7 +5822,6 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -6823,11 +5831,11 @@ } }, "node_modules/react-force-graph-2d": { - "version": "1.26.1", - "resolved": "https://registry.npmjs.org/react-force-graph-2d/-/react-force-graph-2d-1.26.1.tgz", - "integrity": "sha512-7dRD0zNjMpeNghc6dwqzKrdWz45kM1/RNQ7OfR/Y4t9cK02NvHjtmA5JeKePAmzZajqmQQFCbTtwxEfhKgcsww==", + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/react-force-graph-2d/-/react-force-graph-2d-1.27.0.tgz", + "integrity": "sha512-NJAc7lWvY8PxBMn2uFXDDaeLcgJp37IYF6r0geOJlmMs5Lsf0IDmr35T7KNszHV3OUmTrZuPlyxrrzwGwyKhRg==", "dependencies": { - "force-graph": "^1.47", + "force-graph": "^1.49", "prop-types": "15", "react-kapsule": "^2.5" }, @@ -6846,8 +5854,7 @@ "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "license": "MIT" + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-json-tree": { "version": "0.19.0", @@ -6877,22 +5884,22 @@ } }, "node_modules/react-remove-scroll": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz", - "integrity": "sha512-I2U4JVEsQenxDAKaVa3VZ/JeJZe0/2DxPWL8Tj8yLKctQJQiZM52pn/GWFpSp8dftjM3pSAHVJZscAnC/y+ySQ==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz", + "integrity": "sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==", "dependencies": { - "react-remove-scroll-bar": "^2.3.6", - "react-style-singleton": "^2.2.1", + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", - "use-callback-ref": "^1.3.0", - "use-sidecar": "^1.1.2" + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" }, "engines": { "node": ">=10" }, "peerDependencies": { - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { @@ -6901,20 +5908,19 @@ } }, "node_modules/react-remove-scroll-bar": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz", - "integrity": "sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==", - "license": "MIT", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", "dependencies": { - "react-style-singleton": "^2.2.1", + "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "engines": { "node": ">=10" }, "peerDependencies": { - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -6923,31 +5929,28 @@ } }, "node_modules/react-resizable-panels": { - "version": "2.0.23", - "resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-2.0.23.tgz", - "integrity": "sha512-8ZKTwTU11t/FYwiwhMdtZYYyFxic5U5ysRu2YwfkAgDbUJXFvnWSJqhnzkSlW+mnDoNAzDCrJhdOSXBPA76wug==", - "license": "MIT", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-2.1.7.tgz", + "integrity": "sha512-JtT6gI+nURzhMYQYsx8DKkx6bSoOGFp7A3CwMrOb8y5jFHFyqwo9m68UhmXRw57fRVJksFn1TSlm3ywEQ9vMgA==", "peerDependencies": { - "react": "^16.14.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0" + "react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "node_modules/react-style-singleton": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", - "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==", - "license": "MIT", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", "dependencies": { "get-nonce": "^1.0.0", - "invariant": "^2.2.4", "tslib": "^2.0.0" }, "engines": { "node": ">=10" }, "peerDependencies": { - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { @@ -6985,25 +5988,14 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "license": "MIT", "dependencies": { "pify": "^2.3.0" } }, - "node_modules/read-cache/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -7012,19 +6004,19 @@ } }, "node_modules/reflect.getprototypeof": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.8.tgz", - "integrity": "sha512-B5dj6usc5dkk8uFliwjwDHM8To5/QwdKz9JcBZ8Ic4G1f0YmeeJTtE/ZTdgRFPAfxZFiUaPhZ1Jcs4qeagItGQ==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "dunder-proto": "^1.0.0", - "es-abstract": "^1.23.5", + "es-abstract": "^1.23.9", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.2.0", - "which-builtin-type": "^1.2.0" + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -7061,14 +6053,16 @@ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "node_modules/regexp.prototype.flags": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", - "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", "set-function-name": "^2.0.2" }, "engines": { @@ -7079,18 +6073,20 @@ } }, "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "license": "MIT", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "dependencies": { - "is-core-module": "^2.13.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7100,7 +6096,6 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -7110,7 +6105,6 @@ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, - "license": "MIT", "funding": { "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } @@ -7119,7 +6113,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -7143,7 +6136,6 @@ "url": "https://feross.org/support" } ], - "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -7167,6 +6159,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-regex-test": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", @@ -7188,15 +6196,14 @@ "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" } }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "devOptional": true, "bin": { "semver": "bin/semver.js" @@ -7210,7 +6217,6 @@ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, - "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -7228,7 +6234,6 @@ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, - "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -7239,6 +6244,20 @@ "node": ">= 0.4" } }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/sharp": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", @@ -7282,7 +6301,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -7294,7 +6312,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "license": "MIT", "engines": { "node": ">=8" } @@ -7375,7 +6392,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "license": "ISC", "engines": { "node": ">=14" }, @@ -7408,6 +6424,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/stable-hash": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz", + "integrity": "sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==", + "dev": true + }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -7420,7 +6442,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -7438,7 +6459,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -7448,37 +6468,28 @@ "node": ">=8" } }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/string-width-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "node_modules/string-width/node_modules/ansi-regex": { + "node_modules/string-width-cjs/node_modules/strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "license": "MIT", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { - "ansi-regex": "^6.0.1" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=8" } }, "node_modules/string.prototype.includes": { @@ -7496,23 +6507,24 @@ } }, "node_modules/string.prototype.matchall": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", - "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", + "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "regexp.prototype.flags": "^1.5.2", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", "set-function-name": "^2.0.2", - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -7575,7 +6587,6 @@ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -7589,15 +6600,17 @@ } }, "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dependencies": { - "ansi-regex": "^5.0.1" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/strip-ansi-cjs": { @@ -7605,7 +6618,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -7613,12 +6625,19 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -7628,7 +6647,6 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" }, @@ -7662,7 +6680,6 @@ "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", - "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", @@ -7685,7 +6702,6 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -7697,7 +6713,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -7706,18 +6721,18 @@ } }, "node_modules/tailwind-merge": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.5.tgz", - "integrity": "sha512-0LXunzzAZzo0tEPxV3I297ffKZPlKDrjj7NXphC8V5ak9yHC5zRmxnOe2m/Rd/7ivsOMJe3JZ2JVocoDdQTRBA==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.0.tgz", + "integrity": "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==", "funding": { "type": "github", "url": "https://github.com/sponsors/dcastil" } }, "node_modules/tailwindcss": { - "version": "3.4.15", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.15.tgz", - "integrity": "sha512-r4MeXnfBmSOuKUWmXe6h2CcyfzJCEk4F0pptO5jlnYSIViUkVmsawj80N5h2lO3gwcmSb4n3PuN+e+GC1Guylw==", + "version": "3.4.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", + "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -7728,7 +6743,7 @@ "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.21.6", - "lilconfig": "^2.1.0", + "lilconfig": "^3.1.3", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", @@ -7754,17 +6769,41 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", - "license": "MIT", "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } }, + "node_modules/tailwindcss/node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/tailwindcss/node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } @@ -7781,7 +6820,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "license": "MIT", "dependencies": { "any-promise": "^1.0.0" } @@ -7790,7 +6828,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "license": "MIT", "dependencies": { "thenify": ">= 3.1.0 < 4" }, @@ -7807,7 +6844,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -7816,30 +6852,27 @@ } }, "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", + "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", "dev": true, - "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18.12" }, "peerDependencies": { - "typescript": ">=4.2.0" + "typescript": ">=4.8.4" } }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "license": "Apache-2.0" + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, - "license": "MIT", "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", @@ -7857,7 +6890,6 @@ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, - "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -7866,32 +6898,30 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -7901,18 +6931,18 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.3.tgz", - "integrity": "sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "reflect.getprototypeof": "^1.0.6" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" }, "engines": { "node": ">= 0.4" @@ -7942,11 +6972,10 @@ } }, "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "dev": true, - "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -7956,16 +6985,18 @@ } }, "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, - "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bound": "^1.0.3", "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7978,9 +7009,9 @@ "dev": true }, "node_modules/update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", + "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", "funding": [ { "type": "opencollective", @@ -7997,7 +7028,7 @@ ], "dependencies": { "escalade": "^3.2.0", - "picocolors": "^1.1.0" + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -8011,16 +7042,14 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, "node_modules/use-callback-ref": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz", - "integrity": "sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==", - "license": "MIT", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", "dependencies": { "tslib": "^2.0.0" }, @@ -8028,8 +7057,8 @@ "node": ">=10" }, "peerDependencies": { - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { @@ -8038,10 +7067,9 @@ } }, "node_modules/use-sidecar": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", - "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==", - "license": "MIT", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" @@ -8050,8 +7078,8 @@ "node": ">=10" }, "peerDependencies": { - "@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { @@ -8062,8 +7090,7 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "license": "MIT" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/utrie": { "version": "1.0.2", @@ -8077,7 +7104,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -8153,15 +7179,16 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.16", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.16.tgz", - "integrity": "sha512-g+N+GAWiRj66DngFwHvISJd+ITsyphZvD1vChfVg6cEdnzy53GzB3oy0fUNlvhz7H7+MiqhYr26qxQShCpKTTQ==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", + "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", "dev": true, "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "for-each": "^0.3.3", - "gopd": "^1.0.1", + "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" }, "engines": { @@ -8176,7 +7203,6 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -8185,7 +7211,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -8203,7 +7228,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -8216,17 +7240,23 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -8236,23 +7266,21 @@ "node": ">=8" } }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "license": "MIT", - "engines": { - "node": ">=12" + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "engines": { + "node": ">=8" } }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "license": "MIT", "engines": { "node": ">=12" }, @@ -8260,21 +7288,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -8284,10 +7297,9 @@ } }, "node_modules/yaml": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", - "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", - "license": "ISC", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", + "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", "bin": { "yaml": "bin.mjs" }, @@ -8300,7 +7312,6 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, diff --git a/package.json b/package.json index 7554b92c..fcba9a30 100644 --- a/package.json +++ b/package.json @@ -9,44 +9,44 @@ "lint": "next lint" }, "dependencies": { - "@radix-ui/react-checkbox": "^1.1.2", - "@radix-ui/react-dialog": "^1.1.2", - "@radix-ui/react-dropdown-menu": "^2.1.2", - "@radix-ui/react-hover-card": "^1.1.2", - "@radix-ui/react-progress": "^1.1.0", - "@radix-ui/react-select": "^2.1.2", + "@radix-ui/react-checkbox": "^1.1.4", + "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-dropdown-menu": "^2.1.6", + "@radix-ui/react-hover-card": "^1.1.6", + "@radix-ui/react-progress": "^1.1.2", + "@radix-ui/react-select": "^2.1.6", "@radix-ui/react-slot": "^1.0.2", - "@radix-ui/react-toast": "^1.2.2", - "@radix-ui/react-tooltip": "^1.1.4", + "@radix-ui/react-toast": "^1.2.6", + "@radix-ui/react-tooltip": "^1.1.8", "@types/react-gtm-module": "^2.0.4", "autoprefixer": "^10.4.20", "canvas2svg": "^1.0.16", "class-variance-authority": "^0.7.1", - "clsx": "^2.1.0", + "clsx": "^2.1.1", "html2canvas": "^1.4.1", "lucide-react": "^0.441.0", - "next": "^15.1.2", + "next": "^15.1.7", "playwright": "^1.49.1", - "react": "^18", - "react-dom": "^18", - "react-force-graph-2d": "^1.25.8", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-force-graph-2d": "^1.27.0", "react-gtm-module": "^2.0.11", "react-json-tree": "^0.19.0", - "react-resizable-panels": "^2.0.20", + "react-resizable-panels": "^2.1.7", "react-syntax-highlighter": "^15.6.1", "react-type-animation": "^3.2.0", - "tailwind-merge": "^2.5.5", + "tailwind-merge": "^2.6.0", "tailwindcss-animate": "^1.0.7" }, "devDependencies": { - "@playwright/test": "^1.49.1", - "@types/node": "^22.10.2", - "@types/react": "^18", - "@types/react-dom": "^18", + "@playwright/test": "^1.50.1", + "@types/node": "^22.13.1", + "@types/react": "^18.3.18", + "@types/react-dom": "^18.3.5", "@types/react-syntax-highlighter": "^15.5.13", - "eslint": "^9", - "eslint-config-next": "^15.1.2", - "tailwindcss": "^3.4.3", - "typescript": "^5" + "eslint": "^9.20.1", + "eslint-config-next": "^15.1.7", + "tailwindcss": "^3.4.17", + "typescript": "^5.7.3" } } From 7e00636e1f9c7583b11289593786be7a7d382dfe Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Thu, 13 Feb 2025 14:13:51 +0200 Subject: [PATCH 042/189] bump lucide-react react-slot --- package-lock.json | 12 ++++++------ package.json | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3577dcc2..febaa568 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "@radix-ui/react-hover-card": "^1.1.6", "@radix-ui/react-progress": "^1.1.2", "@radix-ui/react-select": "^2.1.6", - "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-slot": "^1.1.2", "@radix-ui/react-toast": "^1.2.6", "@radix-ui/react-tooltip": "^1.1.8", "@types/react-gtm-module": "^2.0.4", @@ -23,7 +23,7 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "html2canvas": "^1.4.1", - "lucide-react": "^0.441.0", + "lucide-react": "^0.475.0", "next": "^15.1.7", "playwright": "^1.49.1", "react": "^18.3.1", @@ -5054,11 +5054,11 @@ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" }, "node_modules/lucide-react": { - "version": "0.441.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.441.0.tgz", - "integrity": "sha512-0vfExYtvSDhkC2lqg0zYVW1Uu9GsI4knuV9GP9by5z0Xhc4Zi5RejTxfz9LsjRmCyWVzHCJvxGKZWcRyvQCWVg==", + "version": "0.475.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.475.0.tgz", + "integrity": "sha512-NJzvVu1HwFVeZ+Gwq2q00KygM1aBhy/ZrhY9FsAgJtpB+E4R7uxRk9M2iKvHa6/vNxZydIB59htha4c2vvwvVg==", "peerDependencies": { - "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/math-intrinsics": { diff --git a/package.json b/package.json index fcba9a30..f5fbe959 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "@radix-ui/react-hover-card": "^1.1.6", "@radix-ui/react-progress": "^1.1.2", "@radix-ui/react-select": "^2.1.6", - "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-slot": "^1.1.2", "@radix-ui/react-toast": "^1.2.6", "@radix-ui/react-tooltip": "^1.1.8", "@types/react-gtm-module": "^2.0.4", @@ -24,7 +24,7 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "html2canvas": "^1.4.1", - "lucide-react": "^0.441.0", + "lucide-react": "^0.475.0", "next": "^15.1.7", "playwright": "^1.49.1", "react": "^18.3.1", From e2d753294c888f5e0d61294fc7fb7f9086c3d5f6 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Thu, 30 Jan 2025 16:00:46 +0200 Subject: [PATCH 043/189] commit --- app/components/Input.tsx | 2 +- app/components/chat.tsx | 2 +- app/components/graphView.tsx | 114 +++++++++++++++++++++++++++++++++-- package-lock.json | 6 ++ package.json | 1 + 5 files changed, 118 insertions(+), 7 deletions(-) diff --git a/app/components/Input.tsx b/app/components/Input.tsx index 9ab6da79..bd922485 100644 --- a/app/components/Input.tsx +++ b/app/components/Input.tsx @@ -144,7 +144,7 @@ export default function Input({ onValueChange, handleSubmit, graph, icon, node, }} onKeyDown={handleKeyDown} className={cn("w-full border p-2 rounded-md pointer-events-auto", className)} - value={node?.name || ""} + value={node?.name ?? ""} onChange={(e) => { const newVal = e.target.value const invalidChars = /[%*()\-\[\]{};:"|~]/; diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 6af9ac79..374d0b9f 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -495,7 +495,7 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons { repo &&
-
diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 12ad16f8..d15b5367 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -1,8 +1,8 @@ - import ForceGraph2D from 'react-force-graph-2d'; import { Graph, GraphData, Link, Node } from './model'; import { Dispatch, RefObject, SetStateAction, useEffect, useRef, useState } from 'react'; import { Path } from '../page'; +import dagre from 'dagre'; export interface Position { x: number, @@ -33,8 +33,16 @@ interface Props { } const PATH_COLOR = "#ffde21" -const NODE_SIZE = 6; -const PADDING = 2; +const NODE_SIZE = 6 +const PADDING = 2 +const DAGRE_NODE_WIDTH = 10 +const DAGRE_NODE_HEIGHT = 10 +const RANKS = { + FILE: 0, + CLASS: 1, + FUNCTION: 2, + OTHER: 3 +}; export default function GraphView({ data, @@ -63,6 +71,7 @@ export default function GraphView({ const lastClick = useRef<{ date: Date, name: string }>({ date: new Date(), name: "" }) const [parentWidth, setParentWidth] = useState(0) const [parentHeight, setParentHeight] = useState(0) + const layoutCache = useRef<{key: string, data: GraphData} | null>(null); useEffect(() => { const handleResize = () => { @@ -144,13 +153,97 @@ export default function GraphView({ } } + const getRank = (node: Node) => { + switch (node.category) { + case 'file': return RANKS.FILE; + case 'class': return RANKS.CLASS; + case 'function': return RANKS.FUNCTION; + default: return RANKS.OTHER; + } + } + + const getDagreLayout = (graphData: GraphData) => { + if (!graphData?.nodes?.length) return graphData; + // Cache the previous layout if graph data hasn't changed + const graphKey = JSON.stringify(graphData.nodes.map(n => n.id).join(',') + '|' + graphData.links.map(l => `${l.source.id}-${l.target.id}`).join(',')); + if (layoutCache.current?.key === graphKey) { + return layoutCache.current.data; + } + + const g = new dagre.graphlib.Graph(); + g.setGraph({ + rankdir: 'TB', + nodesep: 30, + align: 'UL', + ranker: 'tight-tree', // Changed from 'network-simplex' for better performance + ranksep: 100, + edgesep: 10, + }); + g.setDefaultEdgeLabel(() => ({})); + + // Batch node operations + const nodeOperations = graphData.nodes.map(node => ({ + id: node.id.toString(), + config: { + width: DAGRE_NODE_WIDTH, + height: DAGRE_NODE_HEIGHT, + rank: getRank(node) + } + })); + + // Perform batch node setting + nodeOperations.forEach(({id, config}) => { + g.setNode(id, config); + }); + + // Batch edge operations + graphData.links.forEach((link) => { + g.setEdge( + link.source.id.toString(), + link.target.id.toString(), + { weight: 1, label: link.label } + ); + }); + + try { + dagre.layout(g); + + // Batch node position updates + graphData.nodes.forEach((node) => { + const nodeWithPos = g.node(node.id.toString()); + if (nodeWithPos) { + node.x = nodeWithPos.x; + node.y = nodeWithPos.y; + } + }); + + // Cache the result + layoutCache.current = { + key: graphKey, + data: graphData + }; + + // Defer zoom to fit + requestAnimationFrame(() => { + if (chartRef.current) { + chartRef.current.zoomToFit(100, 50); + } + }); + + } catch (error) { + console.error('Error in dagre layout:', error); + } + + return graphData; + }; + return (
Date: Sun, 16 Feb 2025 11:07:26 +0200 Subject: [PATCH 044/189] commit --- app/components/code-graph.tsx | 10 +++ app/components/graphView.tsx | 84 +++++++++++++------ app/globals.css | 24 ++++++ components.json | 8 +- components/ui/switch.tsx | 29 +++++++ lib/utils.ts | 2 +- package-lock.json | 113 ++++++++++++++++++++++++-- package.json | 3 +- tailwind.config.js | 149 +++++++++++++++++++--------------- 9 files changed, 318 insertions(+), 104 deletions(-) create mode 100644 components/ui/switch.tsx diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 8e0341f8..064d6584 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -15,6 +15,7 @@ import dynamic from 'next/dynamic'; import { Position } from "./graphView"; import { prepareArg } from '../utils'; import { NodeObject } from "react-force-graph-2d"; +import { Switch } from "@/components/ui/switch" const GraphView = dynamic(() => import('./graphView')); @@ -68,6 +69,7 @@ export function CodeGraph({ const [cooldownTicks, setCooldownTicks] = useState(0) const [cooldownTime, setCooldownTime] = useState(0) const containerRef = useRef(null); + const [isTreeLayout, setIsTreeLayout] = useState(false); useEffect(() => { setData({ ...graph.Elements }) @@ -376,6 +378,13 @@ export function CodeGraph({
} +
+

Tree Layout

+ +
:
diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index d15b5367..5b38168a 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -30,6 +30,7 @@ interface Props { setCooldownTicks: Dispatch> cooldownTime: number | undefined setCooldownTime: Dispatch> + isTreeLayout: boolean } const PATH_COLOR = "#ffde21" @@ -64,7 +65,8 @@ export default function GraphView({ cooldownTicks, cooldownTime, setCooldownTicks, - setCooldownTime + setCooldownTime, + isTreeLayout }: Props) { const parentRef = useRef(null) @@ -104,6 +106,18 @@ export default function GraphView({ setCooldownTicks(undefined) }, [graph.getElements().length]) + useEffect(() => { + if (!isTreeLayout && chartRef.current) { + data.nodes.forEach(node => { + node.x = undefined; + node.y = undefined; + }); + setData({...data}); + + chartRef.current.d3ReheatSimulation(); + } + }, [isTreeLayout]); + const unsetSelectedObjects = (evt?: MouseEvent) => { if (evt?.ctrlKey || (!selectedObj && selectedObjects.length === 0)) return setSelectedObj(undefined) @@ -155,16 +169,16 @@ export default function GraphView({ const getRank = (node: Node) => { switch (node.category) { - case 'file': return RANKS.FILE; - case 'class': return RANKS.CLASS; - case 'function': return RANKS.FUNCTION; + case 'File': return RANKS.FILE; + case 'Class': return RANKS.CLASS; + case 'Function': return RANKS.FUNCTION; default: return RANKS.OTHER; } } const getDagreLayout = (graphData: GraphData) => { if (!graphData?.nodes?.length) return graphData; - // Cache the previous layout if graph data hasn't changed + const graphKey = JSON.stringify(graphData.nodes.map(n => n.id).join(',') + '|' + graphData.links.map(l => `${l.source.id}-${l.target.id}`).join(',')); if (layoutCache.current?.key === graphKey) { return layoutCache.current.data; @@ -173,30 +187,47 @@ export default function GraphView({ const g = new dagre.graphlib.Graph(); g.setGraph({ rankdir: 'TB', - nodesep: 30, + nodesep: 10, align: 'UL', - ranker: 'tight-tree', // Changed from 'network-simplex' for better performance + ranker: 'network-simplex', ranksep: 100, edgesep: 10, }); g.setDefaultEdgeLabel(() => ({})); - // Batch node operations - const nodeOperations = graphData.nodes.map(node => ({ - id: node.id.toString(), - config: { + // Group nodes by their category + const nodesByRank: Record = { + [RANKS.FILE]: [], + [RANKS.CLASS]: [], + [RANKS.FUNCTION]: [], + [RANKS.OTHER]: [], + }; + + // First pass: add nodes and collect them by rank + graphData.nodes.forEach(node => { + const rank = getRank(node); + g.setNode(node.id.toString(), { width: DAGRE_NODE_WIDTH, height: DAGRE_NODE_HEIGHT, - rank: getRank(node) - } - })); + rank: rank + }); + nodesByRank[rank].push(node.id.toString()); + }); - // Perform batch node setting - nodeOperations.forEach(({id, config}) => { - g.setNode(id, config); + // Add same rank constraints + Object.values(nodesByRank).forEach(rankNodes => { + if (rankNodes.length > 1) { + for (let i = 1; i < rankNodes.length; i++) { + g.setEdge(rankNodes[i-1], rankNodes[i], { + weight: 0, + type: 'RANK', + style: 'invisible' + }); + } + } }); - // Batch edge operations + // Add actual edges after rank constraints graphData.links.forEach((link) => { g.setEdge( link.source.id.toString(), @@ -208,25 +239,25 @@ export default function GraphView({ try { dagre.layout(g); - // Batch node position updates + // Update node positions graphData.nodes.forEach((node) => { const nodeWithPos = g.node(node.id.toString()); if (nodeWithPos) { node.x = nodeWithPos.x; - node.y = nodeWithPos.y; + // Force Y position based on rank + const rank = getRank(node); + node.y = rank * 100; // Use fixed Y positions based on rank } }); - // Cache the result layoutCache.current = { key: graphKey, data: graphData }; - // Defer zoom to fit requestAnimationFrame(() => { if (chartRef.current) { - chartRef.current.zoomToFit(100, 50); + chartRef.current.zoomToFit(1000, 40); } }); @@ -243,7 +274,8 @@ export default function GraphView({ ref={chartRef} height={parentHeight} width={parentWidth} - graphData={getDagreLayout(data)} + key={`graph-${isTreeLayout}`} + graphData={isTreeLayout ? getDagreLayout(data) : data} nodeVisibility="visible" linkVisibility="visible" linkCurvature="curve" @@ -383,8 +415,8 @@ export default function GraphView({ setCooldownTicks(0) setCooldownTime(0) }} - cooldownTicks={cooldownTicks} - cooldownTime={cooldownTime} + cooldownTicks={isTreeLayout ? 0 : cooldownTicks} + cooldownTime={isTreeLayout ? 0 : cooldownTime} />
) diff --git a/app/globals.css b/app/globals.css index 51fd8ab8..ea80754a 100644 --- a/app/globals.css +++ b/app/globals.css @@ -33,6 +33,16 @@ --ring: 222.2 84% 4.9%; --radius: 0.5rem; + + --chart-1: 12 76% 61%; + + --chart-2: 173 58% 39%; + + --chart-3: 197 37% 24%; + + --chart-4: 43 74% 66%; + + --chart-5: 27 87% 67%; } .dark { @@ -64,6 +74,11 @@ --input: 217.2 32.6% 17.5%; --ring: 212.7 26.8% 83.9%; --radius: 0.5rem; + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; } } @@ -120,4 +135,13 @@ ::-webkit-scrollbar-thumb:hover { background-color: #a8bbbf; +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } } \ No newline at end of file diff --git a/components.json b/components.json index 811d2dbc..05fa7462 100644 --- a/components.json +++ b/components.json @@ -12,6 +12,10 @@ }, "aliases": { "components": "@/components", - "utils": "@/lib/utils" - } + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "iconLibrary": "lucide" } \ No newline at end of file diff --git a/components/ui/switch.tsx b/components/ui/switch.tsx new file mode 100644 index 00000000..bc69cf2d --- /dev/null +++ b/components/ui/switch.tsx @@ -0,0 +1,29 @@ +"use client" + +import * as React from "react" +import * as SwitchPrimitives from "@radix-ui/react-switch" + +import { cn } from "@/lib/utils" + +const Switch = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +Switch.displayName = SwitchPrimitives.Root.displayName + +export { Switch } diff --git a/lib/utils.ts b/lib/utils.ts index d084ccad..bd0c391d 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -1,4 +1,4 @@ -import { type ClassValue, clsx } from "clsx" +import { clsx, type ClassValue } from "clsx" import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { diff --git a/package-lock.json b/package-lock.json index 2503107b..afa2f5f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@radix-ui/react-progress": "^1.1.0", "@radix-ui/react-select": "^2.1.2", "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-switch": "^1.1.3", "@radix-ui/react-toast": "^1.2.2", "@radix-ui/react-tooltip": "^1.1.4", "@types/dagre": "^0.7.52", @@ -23,7 +24,7 @@ "canvas2svg": "^1.0.16", "class-variance-authority": "^0.7.1", "clsx": "^2.1.0", - "html2canvas": "^1.4.1", + "dagre": "^0.8.5", "lucide-react": "^0.441.0", "next": "^15.1.2", "playwright": "^1.49.1", @@ -35,7 +36,7 @@ "react-resizable-panels": "^2.0.20", "react-syntax-highlighter": "^15.6.1", "react-type-animation": "^3.2.0", - "tailwind-merge": "^2.5.5", + "tailwind-merge": "^2.6.0", "tailwindcss-animate": "^1.0.7" }, "devDependencies": { @@ -2122,6 +2123,106 @@ } } }, + "node_modules/@radix-ui/react-switch": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.1.3.tgz", + "integrity": "sha512-1nc+vjEOQkJVsJtWPSiISGT6OKm4SiOdjMo+/icLxo2G4vxz1GntC5MzfL4v8ey9OEfw787QCD1y3mUv0NiFEQ==", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-previous": "1.1.0", + "@radix-ui/react-use-size": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", + "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==" + }, + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", + "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-primitive": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz", + "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==", + "dependencies": { + "@radix-ui/react-slot": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", + "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-toast": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.3.tgz", @@ -3582,7 +3683,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", "engines": { "node": ">=6" } @@ -7712,9 +7812,9 @@ } }, "node_modules/tailwind-merge": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.5.tgz", - "integrity": "sha512-0LXunzzAZzo0tEPxV3I297ffKZPlKDrjj7NXphC8V5ak9yHC5zRmxnOe2m/Rd/7ivsOMJe3JZ2JVocoDdQTRBA==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.0.tgz", + "integrity": "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==", "funding": { "type": "github", "url": "https://github.com/sponsors/dcastil" @@ -7760,7 +7860,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", - "license": "MIT", "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } diff --git a/package.json b/package.json index 00876af0..da3ead65 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@radix-ui/react-progress": "^1.1.0", "@radix-ui/react-select": "^2.1.2", "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-switch": "^1.1.3", "@radix-ui/react-toast": "^1.2.2", "@radix-ui/react-tooltip": "^1.1.4", "@types/dagre": "^0.7.52", @@ -36,7 +37,7 @@ "react-resizable-panels": "^2.0.20", "react-syntax-highlighter": "^15.6.1", "react-type-animation": "^3.2.0", - "tailwind-merge": "^2.5.5", + "tailwind-merge": "^2.6.0", "tailwindcss-animate": "^1.0.7" }, "devDependencies": { diff --git a/tailwind.config.js b/tailwind.config.js index 14d51792..bad191f5 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -14,73 +14,88 @@ module.exports = { ], prefix: "", theme: { - container: { - center: true, - padding: "2rem", - screens: { - "2xl": "1400px", - }, - }, - extend: { - colors: { - blue: "#7466FF", - pink: "#FF66B3", - orange: "#FF804D", - turquoise: "#80E6E6", - border: "hsl(var(--border))", - input: "hsl(var(--input))", - ring: "hsl(var(--ring))", - background: "hsl(var(--background))", - foreground: "hsl(var(--foreground))", - primary: { - DEFAULT: "hsl(var(--primary))", - foreground: "hsl(var(--primary-foreground))", - }, - secondary: { - DEFAULT: "hsl(var(--secondary))", - foreground: "hsl(var(--secondary-foreground))", - }, - destructive: { - DEFAULT: "hsl(var(--destructive))", - foreground: "hsl(var(--destructive-foreground))", - }, - muted: { - DEFAULT: "hsl(var(--muted))", - foreground: "hsl(var(--muted-foreground))", - }, - accent: { - DEFAULT: "hsl(var(--accent))", - foreground: "hsl(var(--accent-foreground))", - }, - popover: { - DEFAULT: "hsl(var(--popover))", - foreground: "hsl(var(--popover-foreground))", - }, - card: { - DEFAULT: "hsl(var(--card))", - foreground: "hsl(var(--card-foreground))", - }, - }, - borderRadius: { - lg: "var(--radius)", - md: "calc(var(--radius) - 2px)", - sm: "calc(var(--radius) - 4px)", - }, - keyframes: { - "accordion-down": { - from: { height: "0" }, - to: { height: "var(--radix-accordion-content-height)" }, - }, - "accordion-up": { - from: { height: "var(--radix-accordion-content-height)" }, - to: { height: "0" }, - }, - }, - animation: { - "accordion-down": "accordion-down 0.2s ease-out", - "accordion-up": "accordion-up 0.2s ease-out", - }, - }, + container: { + center: true, + padding: '2rem', + screens: { + '2xl': '1400px' + } + }, + extend: { + colors: { + blue: '#7466FF', + pink: '#FF66B3', + orange: '#FF804D', + turquoise: '#80E6E6', + border: 'hsl(var(--border))', + input: 'hsl(var(--input))', + ring: 'hsl(var(--ring))', + background: 'hsl(var(--background))', + foreground: 'hsl(var(--foreground))', + primary: { + DEFAULT: 'hsl(var(--primary))', + foreground: 'hsl(var(--primary-foreground))' + }, + secondary: { + DEFAULT: 'hsl(var(--secondary))', + foreground: 'hsl(var(--secondary-foreground))' + }, + destructive: { + DEFAULT: 'hsl(var(--destructive))', + foreground: 'hsl(var(--destructive-foreground))' + }, + muted: { + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))' + }, + accent: { + DEFAULT: 'hsl(var(--accent))', + foreground: 'hsl(var(--accent-foreground))' + }, + popover: { + DEFAULT: 'hsl(var(--popover))', + foreground: 'hsl(var(--popover-foreground))' + }, + card: { + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))' + }, + chart: { + '1': 'hsl(var(--chart-1))', + '2': 'hsl(var(--chart-2))', + '3': 'hsl(var(--chart-3))', + '4': 'hsl(var(--chart-4))', + '5': 'hsl(var(--chart-5))' + } + }, + borderRadius: { + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)' + }, + keyframes: { + 'accordion-down': { + from: { + height: '0' + }, + to: { + height: 'var(--radix-accordion-content-height)' + } + }, + 'accordion-up': { + from: { + height: 'var(--radix-accordion-content-height)' + }, + to: { + height: '0' + } + } + }, + animation: { + 'accordion-down': 'accordion-down 0.2s ease-out', + 'accordion-up': 'accordion-up 0.2s ease-out' + } + } }, plugins: [require("tailwindcss-animate")], } \ No newline at end of file From a53c73f4eb7c325f0e3f696f00787edb4924e4dd Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Sun, 16 Feb 2025 11:30:00 +0200 Subject: [PATCH 045/189] Revert "commit" This reverts commit 1c7cc924f637d95963f4525f1d6e04c77158d5b4. --- app/components/code-graph.tsx | 10 --- app/components/graphView.tsx | 84 ++++++------------- app/globals.css | 24 ------ components.json | 8 +- components/ui/switch.tsx | 29 ------- lib/utils.ts | 2 +- package-lock.json | 113 ++------------------------ package.json | 3 +- tailwind.config.js | 149 +++++++++++++++------------------- 9 files changed, 104 insertions(+), 318 deletions(-) delete mode 100644 components/ui/switch.tsx diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 064d6584..8e0341f8 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -15,7 +15,6 @@ import dynamic from 'next/dynamic'; import { Position } from "./graphView"; import { prepareArg } from '../utils'; import { NodeObject } from "react-force-graph-2d"; -import { Switch } from "@/components/ui/switch" const GraphView = dynamic(() => import('./graphView')); @@ -69,7 +68,6 @@ export function CodeGraph({ const [cooldownTicks, setCooldownTicks] = useState(0) const [cooldownTime, setCooldownTime] = useState(0) const containerRef = useRef(null); - const [isTreeLayout, setIsTreeLayout] = useState(false); useEffect(() => { setData({ ...graph.Elements }) @@ -378,13 +376,6 @@ export function CodeGraph({
} -
-

Tree Layout

- -
:
diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 5b38168a..d15b5367 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -30,7 +30,6 @@ interface Props { setCooldownTicks: Dispatch> cooldownTime: number | undefined setCooldownTime: Dispatch> - isTreeLayout: boolean } const PATH_COLOR = "#ffde21" @@ -65,8 +64,7 @@ export default function GraphView({ cooldownTicks, cooldownTime, setCooldownTicks, - setCooldownTime, - isTreeLayout + setCooldownTime }: Props) { const parentRef = useRef(null) @@ -106,18 +104,6 @@ export default function GraphView({ setCooldownTicks(undefined) }, [graph.getElements().length]) - useEffect(() => { - if (!isTreeLayout && chartRef.current) { - data.nodes.forEach(node => { - node.x = undefined; - node.y = undefined; - }); - setData({...data}); - - chartRef.current.d3ReheatSimulation(); - } - }, [isTreeLayout]); - const unsetSelectedObjects = (evt?: MouseEvent) => { if (evt?.ctrlKey || (!selectedObj && selectedObjects.length === 0)) return setSelectedObj(undefined) @@ -169,16 +155,16 @@ export default function GraphView({ const getRank = (node: Node) => { switch (node.category) { - case 'File': return RANKS.FILE; - case 'Class': return RANKS.CLASS; - case 'Function': return RANKS.FUNCTION; + case 'file': return RANKS.FILE; + case 'class': return RANKS.CLASS; + case 'function': return RANKS.FUNCTION; default: return RANKS.OTHER; } } const getDagreLayout = (graphData: GraphData) => { if (!graphData?.nodes?.length) return graphData; - + // Cache the previous layout if graph data hasn't changed const graphKey = JSON.stringify(graphData.nodes.map(n => n.id).join(',') + '|' + graphData.links.map(l => `${l.source.id}-${l.target.id}`).join(',')); if (layoutCache.current?.key === graphKey) { return layoutCache.current.data; @@ -187,47 +173,30 @@ export default function GraphView({ const g = new dagre.graphlib.Graph(); g.setGraph({ rankdir: 'TB', - nodesep: 10, + nodesep: 30, align: 'UL', - ranker: 'network-simplex', + ranker: 'tight-tree', // Changed from 'network-simplex' for better performance ranksep: 100, edgesep: 10, }); g.setDefaultEdgeLabel(() => ({})); - // Group nodes by their category - const nodesByRank: Record = { - [RANKS.FILE]: [], - [RANKS.CLASS]: [], - [RANKS.FUNCTION]: [], - [RANKS.OTHER]: [], - }; - - // First pass: add nodes and collect them by rank - graphData.nodes.forEach(node => { - const rank = getRank(node); - g.setNode(node.id.toString(), { + // Batch node operations + const nodeOperations = graphData.nodes.map(node => ({ + id: node.id.toString(), + config: { width: DAGRE_NODE_WIDTH, height: DAGRE_NODE_HEIGHT, - rank: rank - }); - nodesByRank[rank].push(node.id.toString()); - }); - - // Add same rank constraints - Object.values(nodesByRank).forEach(rankNodes => { - if (rankNodes.length > 1) { - for (let i = 1; i < rankNodes.length; i++) { - g.setEdge(rankNodes[i-1], rankNodes[i], { - weight: 0, - type: 'RANK', - style: 'invisible' - }); - } + rank: getRank(node) } + })); + + // Perform batch node setting + nodeOperations.forEach(({id, config}) => { + g.setNode(id, config); }); - // Add actual edges after rank constraints + // Batch edge operations graphData.links.forEach((link) => { g.setEdge( link.source.id.toString(), @@ -239,25 +208,25 @@ export default function GraphView({ try { dagre.layout(g); - // Update node positions + // Batch node position updates graphData.nodes.forEach((node) => { const nodeWithPos = g.node(node.id.toString()); if (nodeWithPos) { node.x = nodeWithPos.x; - // Force Y position based on rank - const rank = getRank(node); - node.y = rank * 100; // Use fixed Y positions based on rank + node.y = nodeWithPos.y; } }); + // Cache the result layoutCache.current = { key: graphKey, data: graphData }; + // Defer zoom to fit requestAnimationFrame(() => { if (chartRef.current) { - chartRef.current.zoomToFit(1000, 40); + chartRef.current.zoomToFit(100, 50); } }); @@ -274,8 +243,7 @@ export default function GraphView({ ref={chartRef} height={parentHeight} width={parentWidth} - key={`graph-${isTreeLayout}`} - graphData={isTreeLayout ? getDagreLayout(data) : data} + graphData={getDagreLayout(data)} nodeVisibility="visible" linkVisibility="visible" linkCurvature="curve" @@ -415,8 +383,8 @@ export default function GraphView({ setCooldownTicks(0) setCooldownTime(0) }} - cooldownTicks={isTreeLayout ? 0 : cooldownTicks} - cooldownTime={isTreeLayout ? 0 : cooldownTime} + cooldownTicks={cooldownTicks} + cooldownTime={cooldownTime} />
) diff --git a/app/globals.css b/app/globals.css index ea80754a..51fd8ab8 100644 --- a/app/globals.css +++ b/app/globals.css @@ -33,16 +33,6 @@ --ring: 222.2 84% 4.9%; --radius: 0.5rem; - - --chart-1: 12 76% 61%; - - --chart-2: 173 58% 39%; - - --chart-3: 197 37% 24%; - - --chart-4: 43 74% 66%; - - --chart-5: 27 87% 67%; } .dark { @@ -74,11 +64,6 @@ --input: 217.2 32.6% 17.5%; --ring: 212.7 26.8% 83.9%; --radius: 0.5rem; - --chart-1: 220 70% 50%; - --chart-2: 160 60% 45%; - --chart-3: 30 80% 55%; - --chart-4: 280 65% 60%; - --chart-5: 340 75% 55%; } } @@ -135,13 +120,4 @@ ::-webkit-scrollbar-thumb:hover { background-color: #a8bbbf; -} - -@layer base { - * { - @apply border-border; - } - body { - @apply bg-background text-foreground; - } } \ No newline at end of file diff --git a/components.json b/components.json index 05fa7462..811d2dbc 100644 --- a/components.json +++ b/components.json @@ -12,10 +12,6 @@ }, "aliases": { "components": "@/components", - "utils": "@/lib/utils", - "ui": "@/components/ui", - "lib": "@/lib", - "hooks": "@/hooks" - }, - "iconLibrary": "lucide" + "utils": "@/lib/utils" + } } \ No newline at end of file diff --git a/components/ui/switch.tsx b/components/ui/switch.tsx deleted file mode 100644 index bc69cf2d..00000000 --- a/components/ui/switch.tsx +++ /dev/null @@ -1,29 +0,0 @@ -"use client" - -import * as React from "react" -import * as SwitchPrimitives from "@radix-ui/react-switch" - -import { cn } from "@/lib/utils" - -const Switch = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - - -)) -Switch.displayName = SwitchPrimitives.Root.displayName - -export { Switch } diff --git a/lib/utils.ts b/lib/utils.ts index bd0c391d..d084ccad 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -1,4 +1,4 @@ -import { clsx, type ClassValue } from "clsx" +import { type ClassValue, clsx } from "clsx" import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { diff --git a/package-lock.json b/package-lock.json index afa2f5f9..2503107b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,6 @@ "@radix-ui/react-progress": "^1.1.0", "@radix-ui/react-select": "^2.1.2", "@radix-ui/react-slot": "^1.0.2", - "@radix-ui/react-switch": "^1.1.3", "@radix-ui/react-toast": "^1.2.2", "@radix-ui/react-tooltip": "^1.1.4", "@types/dagre": "^0.7.52", @@ -24,7 +23,7 @@ "canvas2svg": "^1.0.16", "class-variance-authority": "^0.7.1", "clsx": "^2.1.0", - "dagre": "^0.8.5", + "html2canvas": "^1.4.1", "lucide-react": "^0.441.0", "next": "^15.1.2", "playwright": "^1.49.1", @@ -36,7 +35,7 @@ "react-resizable-panels": "^2.0.20", "react-syntax-highlighter": "^15.6.1", "react-type-animation": "^3.2.0", - "tailwind-merge": "^2.6.0", + "tailwind-merge": "^2.5.5", "tailwindcss-animate": "^1.0.7" }, "devDependencies": { @@ -2123,106 +2122,6 @@ } } }, - "node_modules/@radix-ui/react-switch": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.1.3.tgz", - "integrity": "sha512-1nc+vjEOQkJVsJtWPSiISGT6OKm4SiOdjMo+/icLxo2G4vxz1GntC5MzfL4v8ey9OEfw787QCD1y3mUv0NiFEQ==", - "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-previous": "1.1.0", - "@radix-ui/react-use-size": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", - "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==" - }, - "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", - "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-context": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", - "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-primitive": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz", - "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==", - "dependencies": { - "@radix-ui/react-slot": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", - "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/@radix-ui/react-toast": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.3.tgz", @@ -3683,6 +3582,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", "engines": { "node": ">=6" } @@ -7812,9 +7712,9 @@ } }, "node_modules/tailwind-merge": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.0.tgz", - "integrity": "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.5.tgz", + "integrity": "sha512-0LXunzzAZzo0tEPxV3I297ffKZPlKDrjj7NXphC8V5ak9yHC5zRmxnOe2m/Rd/7ivsOMJe3JZ2JVocoDdQTRBA==", "funding": { "type": "github", "url": "https://github.com/sponsors/dcastil" @@ -7860,6 +7760,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", + "license": "MIT", "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } diff --git a/package.json b/package.json index da3ead65..00876af0 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,6 @@ "@radix-ui/react-progress": "^1.1.0", "@radix-ui/react-select": "^2.1.2", "@radix-ui/react-slot": "^1.0.2", - "@radix-ui/react-switch": "^1.1.3", "@radix-ui/react-toast": "^1.2.2", "@radix-ui/react-tooltip": "^1.1.4", "@types/dagre": "^0.7.52", @@ -37,7 +36,7 @@ "react-resizable-panels": "^2.0.20", "react-syntax-highlighter": "^15.6.1", "react-type-animation": "^3.2.0", - "tailwind-merge": "^2.6.0", + "tailwind-merge": "^2.5.5", "tailwindcss-animate": "^1.0.7" }, "devDependencies": { diff --git a/tailwind.config.js b/tailwind.config.js index bad191f5..14d51792 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -14,88 +14,73 @@ module.exports = { ], prefix: "", theme: { - container: { - center: true, - padding: '2rem', - screens: { - '2xl': '1400px' - } - }, - extend: { - colors: { - blue: '#7466FF', - pink: '#FF66B3', - orange: '#FF804D', - turquoise: '#80E6E6', - border: 'hsl(var(--border))', - input: 'hsl(var(--input))', - ring: 'hsl(var(--ring))', - background: 'hsl(var(--background))', - foreground: 'hsl(var(--foreground))', - primary: { - DEFAULT: 'hsl(var(--primary))', - foreground: 'hsl(var(--primary-foreground))' - }, - secondary: { - DEFAULT: 'hsl(var(--secondary))', - foreground: 'hsl(var(--secondary-foreground))' - }, - destructive: { - DEFAULT: 'hsl(var(--destructive))', - foreground: 'hsl(var(--destructive-foreground))' - }, - muted: { - DEFAULT: 'hsl(var(--muted))', - foreground: 'hsl(var(--muted-foreground))' - }, - accent: { - DEFAULT: 'hsl(var(--accent))', - foreground: 'hsl(var(--accent-foreground))' - }, - popover: { - DEFAULT: 'hsl(var(--popover))', - foreground: 'hsl(var(--popover-foreground))' - }, - card: { - DEFAULT: 'hsl(var(--card))', - foreground: 'hsl(var(--card-foreground))' - }, - chart: { - '1': 'hsl(var(--chart-1))', - '2': 'hsl(var(--chart-2))', - '3': 'hsl(var(--chart-3))', - '4': 'hsl(var(--chart-4))', - '5': 'hsl(var(--chart-5))' - } - }, - borderRadius: { - lg: 'var(--radius)', - md: 'calc(var(--radius) - 2px)', - sm: 'calc(var(--radius) - 4px)' - }, - keyframes: { - 'accordion-down': { - from: { - height: '0' - }, - to: { - height: 'var(--radix-accordion-content-height)' - } - }, - 'accordion-up': { - from: { - height: 'var(--radix-accordion-content-height)' - }, - to: { - height: '0' - } - } - }, - animation: { - 'accordion-down': 'accordion-down 0.2s ease-out', - 'accordion-up': 'accordion-up 0.2s ease-out' - } - } + container: { + center: true, + padding: "2rem", + screens: { + "2xl": "1400px", + }, + }, + extend: { + colors: { + blue: "#7466FF", + pink: "#FF66B3", + orange: "#FF804D", + turquoise: "#80E6E6", + border: "hsl(var(--border))", + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + primary: { + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + destructive: { + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", + }, + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", + }, + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", + }, + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + keyframes: { + "accordion-down": { + from: { height: "0" }, + to: { height: "var(--radix-accordion-content-height)" }, + }, + "accordion-up": { + from: { height: "var(--radix-accordion-content-height)" }, + to: { height: "0" }, + }, + }, + animation: { + "accordion-down": "accordion-down 0.2s ease-out", + "accordion-up": "accordion-up 0.2s ease-out", + }, + }, }, plugins: [require("tailwindcss-animate")], } \ No newline at end of file From 5a298a4dde0db0d656fb8139c4cc734aacdd4394 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Sun, 16 Feb 2025 11:30:37 +0200 Subject: [PATCH 046/189] Revert "commit" This reverts commit e2d753294c888f5e0d61294fc7fb7f9086c3d5f6. --- app/components/Input.tsx | 2 +- app/components/chat.tsx | 2 +- app/components/graphView.tsx | 114 ++--------------------------------- package-lock.json | 6 -- package.json | 1 - 5 files changed, 7 insertions(+), 118 deletions(-) diff --git a/app/components/Input.tsx b/app/components/Input.tsx index bd922485..9ab6da79 100644 --- a/app/components/Input.tsx +++ b/app/components/Input.tsx @@ -144,7 +144,7 @@ export default function Input({ onValueChange, handleSubmit, graph, icon, node, }} onKeyDown={handleKeyDown} className={cn("w-full border p-2 rounded-md pointer-events-auto", className)} - value={node?.name ?? ""} + value={node?.name || ""} onChange={(e) => { const newVal = e.target.value const invalidChars = /[%*()\-\[\]{};:"|~]/; diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 374d0b9f..6af9ac79 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -495,7 +495,7 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons { repo &&
- diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index d15b5367..12ad16f8 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -1,8 +1,8 @@ + import ForceGraph2D from 'react-force-graph-2d'; import { Graph, GraphData, Link, Node } from './model'; import { Dispatch, RefObject, SetStateAction, useEffect, useRef, useState } from 'react'; import { Path } from '../page'; -import dagre from 'dagre'; export interface Position { x: number, @@ -33,16 +33,8 @@ interface Props { } const PATH_COLOR = "#ffde21" -const NODE_SIZE = 6 -const PADDING = 2 -const DAGRE_NODE_WIDTH = 10 -const DAGRE_NODE_HEIGHT = 10 -const RANKS = { - FILE: 0, - CLASS: 1, - FUNCTION: 2, - OTHER: 3 -}; +const NODE_SIZE = 6; +const PADDING = 2; export default function GraphView({ data, @@ -71,7 +63,6 @@ export default function GraphView({ const lastClick = useRef<{ date: Date, name: string }>({ date: new Date(), name: "" }) const [parentWidth, setParentWidth] = useState(0) const [parentHeight, setParentHeight] = useState(0) - const layoutCache = useRef<{key: string, data: GraphData} | null>(null); useEffect(() => { const handleResize = () => { @@ -153,97 +144,13 @@ export default function GraphView({ } } - const getRank = (node: Node) => { - switch (node.category) { - case 'file': return RANKS.FILE; - case 'class': return RANKS.CLASS; - case 'function': return RANKS.FUNCTION; - default: return RANKS.OTHER; - } - } - - const getDagreLayout = (graphData: GraphData) => { - if (!graphData?.nodes?.length) return graphData; - // Cache the previous layout if graph data hasn't changed - const graphKey = JSON.stringify(graphData.nodes.map(n => n.id).join(',') + '|' + graphData.links.map(l => `${l.source.id}-${l.target.id}`).join(',')); - if (layoutCache.current?.key === graphKey) { - return layoutCache.current.data; - } - - const g = new dagre.graphlib.Graph(); - g.setGraph({ - rankdir: 'TB', - nodesep: 30, - align: 'UL', - ranker: 'tight-tree', // Changed from 'network-simplex' for better performance - ranksep: 100, - edgesep: 10, - }); - g.setDefaultEdgeLabel(() => ({})); - - // Batch node operations - const nodeOperations = graphData.nodes.map(node => ({ - id: node.id.toString(), - config: { - width: DAGRE_NODE_WIDTH, - height: DAGRE_NODE_HEIGHT, - rank: getRank(node) - } - })); - - // Perform batch node setting - nodeOperations.forEach(({id, config}) => { - g.setNode(id, config); - }); - - // Batch edge operations - graphData.links.forEach((link) => { - g.setEdge( - link.source.id.toString(), - link.target.id.toString(), - { weight: 1, label: link.label } - ); - }); - - try { - dagre.layout(g); - - // Batch node position updates - graphData.nodes.forEach((node) => { - const nodeWithPos = g.node(node.id.toString()); - if (nodeWithPos) { - node.x = nodeWithPos.x; - node.y = nodeWithPos.y; - } - }); - - // Cache the result - layoutCache.current = { - key: graphKey, - data: graphData - }; - - // Defer zoom to fit - requestAnimationFrame(() => { - if (chartRef.current) { - chartRef.current.zoomToFit(100, 50); - } - }); - - } catch (error) { - console.error('Error in dagre layout:', error); - } - - return graphData; - }; - return (
Date: Sun, 16 Feb 2025 13:44:50 +0200 Subject: [PATCH 047/189] commit --- app/components/code-graph.tsx | 111 +++++++-------- app/components/combobox.tsx | 2 +- app/components/graphView.tsx | 9 +- app/layout.tsx | 1 - app/page.tsx | 257 +++++++++++++++++++--------------- lib/utils.ts | 20 +++ 6 files changed, 232 insertions(+), 168 deletions(-) diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 8e0341f8..9431cc2c 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -1,6 +1,5 @@ -import { Dispatch, RefObject, SetStateAction, useContext, useEffect, useRef, useState } from "react"; -import { GraphData, Link, Node } from "./model"; -import { GraphContext } from "./provider"; +import { Dispatch, RefObject, SetStateAction, useEffect, useRef, useState } from "react"; +import { Graph, GraphData, Node, Link } from "./model"; import { Toolbar } from "./toolbar"; import { Labels } from "./labels"; import { Download, GitFork, Search, X } from "lucide-react"; @@ -19,6 +18,7 @@ import { NodeObject } from "react-force-graph-2d"; const GraphView = dynamic(() => import('./graphView')); interface Props { + graph: Graph, data: GraphData, setData: Dispatch>, onFetchGraph: (graphName: string) => Promise, @@ -36,6 +36,7 @@ interface Props { } export function CodeGraph({ + graph, data, setData, onFetchGraph, @@ -52,8 +53,6 @@ export function CodeGraph({ selectedPathId }: Props) { - let graph = useContext(GraphContext) - const [url, setURL] = useState(""); const [selectedObj, setSelectedObj] = useState(); const [selectedObjects, setSelectedObjects] = useState([]); @@ -167,17 +166,17 @@ export function CodeGraph({ } const deleteNeighbors = (nodes: Node[]) => { - + if (nodes.length === 0) return; - + const expandedNodes: Node[] = [] - + graph.Elements = { nodes: graph.Elements.nodes.filter(node => { if (!node.collapsed) return true - + const isTarget = graph.Elements.links.some(link => link.target.id === node.id && nodes.some(n => n.id === link.source.id)); - + debugger if (!isTarget) return true @@ -192,7 +191,7 @@ export function CodeGraph({ }), links: graph.Elements.links } - + deleteNeighbors(expandedNodes) graph.removeLinks() @@ -242,7 +241,7 @@ export function CodeGraph({ graph.visibleLinks(true, [chartNode!.id]) setData({ ...graph.Elements }) } - + setSearchNode(chartNode) setTimeout(() => { chart.zoomToFit(1000, 150, (n: NodeObject) => n.id === chartNode!.id); @@ -289,8 +288,9 @@ export function CodeGraph({ }; return ( -
-
+
+
+
{ graph.Id ? -
-
+
+
-
-
-

{nodesCount} Nodes

-

{edgesCount} Edges

-
-
- { - commitIndex !== commits.length && -
-
- -

Display Changes

-
-
-
-

Were added

-
-
-
-

Were edited

-
-
- } - - -
-
+
+
+

{nodesCount} Nodes

+

|

+

{edgesCount} Edges

+
+
+ { + commitIndex !== commits.length && +
+
+ +

Display Changes

+
+
+
+

Were added

+
+
+
+

Were edited

+
+
+ } + + +
+
:
- -

Select a repo to show its graph here

+ +

Select a repo to show its graph here

} diff --git a/app/components/combobox.tsx b/app/components/combobox.tsx index 354fee3f..c22d9334 100644 --- a/app/components/combobox.tsx +++ b/app/components/combobox.tsx @@ -51,7 +51,7 @@ export default function Combobox({ options, setOptions, selectedValue, onSelecte return ( setCreateURL(e.target.value)} - placeholder="Type URL" - /> -
- -
- - : - } - - */} - -
-
-
- - - +
+ setCreateURL(e.target.value)} + placeholder="Type URL" + /> +
+ +
+
+ : + } + + */} + +
+
+
+ + - - - - - - - + + + + + + +
+
+
+ FalkorDB + +
+ + { + graph.Id && +
+ + +
+ } +
) } diff --git a/lib/utils.ts b/lib/utils.ts index d084ccad..faaa3e77 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -4,3 +4,23 @@ import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } + +export function handleZoomToFit(chartRef?: any) { + const chart = chartRef.current + if (chart) { + // Get canvas dimensions + const canvas = document.querySelector('.force-graph-container canvas.clickable') as HTMLCanvasElement; + if (!canvas) return; + + const container = canvas.parentElement; + + if (!container) return; + + // Calculate padding as 1% of the smallest canvas dimension + const minDimension = Math.max(container.clientWidth, container.clientHeight); + + const padding = minDimension * 0.1 + + chart.zoomToFit(1000, padding) + } +} \ No newline at end of file From 5ca84022e24b4fbe209e1011210a57928927e25d Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Sun, 16 Feb 2025 13:53:53 +0200 Subject: [PATCH 048/189] fix comments --- app/components/Input.tsx | 4 +-- app/components/chat.tsx | 50 +++-------------------------------- app/components/code-graph.tsx | 6 ++--- app/components/graphView.tsx | 4 +-- app/components/toolbar.tsx | 6 +++-- 5 files changed, 12 insertions(+), 58 deletions(-) diff --git a/app/components/Input.tsx b/app/components/Input.tsx index 9ab6da79..b99dfb6c 100644 --- a/app/components/Input.tsx +++ b/app/components/Input.tsx @@ -38,9 +38,7 @@ export default function Input({ onValueChange, handleSubmit, graph, icon, node, const timeout = setTimeout(async () => { if (!node?.name) { - if (!node?.name) { - setOptions([]) - } + setOptions([]) setOpen(false) return } diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 6af9ac79..f4ebdfdd 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -4,12 +4,12 @@ import Image from "next/image"; import { AlignLeft, ArrowDown, ArrowRight, ChevronDown, Lightbulb, Undo2 } from "lucide-react"; import { Path } from "../page"; import Input from "./Input"; -import { Graph, GraphData } from "./model"; +import { Graph, GraphData, Link } from "./model"; import { cn } from "@/lib/utils"; import { TypeAnimation } from "react-type-animation"; import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; import { prepareArg } from "../utils"; -import { NodeObject } from "react-force-graph-2d"; +import { NodeObject, ForceGraphMethods } from "react-force-graph-2d"; type PathData = { nodes: any[] @@ -25,50 +25,6 @@ enum MessageTypes { Text, } -const EDGE_STYLE = { - "line-color": "gray", - "target-arrow-color": "gray", - "opacity": 0.5, -} - - -const PATH_EDGE_STYLE = { - width: 0.5, - "line-style": "dashed", - "line-color": "#FF66B3", - "arrow-scale": 0.3, - "target-arrow-color": "#FF66B3", - "opacity": 1 -} - -const SELECTED_PATH_EDGE_STYLE = { - width: 1, - "line-style": "solid", - "line-color": "#FF66B3", - "arrow-scale": 0.6, - "target-arrow-color": "#FF66B3", -}; - -const NODE_STYLE = { - "border-width": 0.5, - "color": "gray", - "border-color": "black", - "background-color": "gray", - "opacity": 0.5 -} - -const PATH_NODE_STYLE = { - "border-width": 0.5, - "border-color": "#FF66B3", - "border-opacity": 1, -} - -const SELECTED_PATH_NODE_STYLE = { - "border-width": 1, - "border-color": "#FF66B3", - "border-opacity": 1, -}; - interface Message { type: MessageTypes; text?: string; @@ -85,7 +41,7 @@ interface Props { isPathResponse: boolean | undefined setIsPathResponse: (isPathResponse: boolean | undefined) => void setData: Dispatch> - chartRef: any + chartRef: React.MutableRefObject> } const SUGGESTIONS = [ diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 8e0341f8..52e38983 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -14,7 +14,7 @@ import { Checkbox } from '@/components/ui/checkbox'; import dynamic from 'next/dynamic'; import { Position } from "./graphView"; import { prepareArg } from '../utils'; -import { NodeObject } from "react-force-graph-2d"; +import { NodeObject, ForceGraphMethods } from "react-force-graph-2d"; const GraphView = dynamic(() => import('./graphView')); @@ -27,7 +27,7 @@ interface Props { setOptions: Dispatch> isShowPath: boolean setPath: Dispatch> - chartRef: RefObject + chartRef: React.MutableRefObject> selectedValue: string selectedPathId: number | undefined setSelectedPathId: (selectedPathId: number) => void @@ -178,8 +178,6 @@ export function CodeGraph({ const isTarget = graph.Elements.links.some(link => link.target.id === node.id && nodes.some(n => n.id === link.source.id)); - debugger - if (!isTarget) return true const deleted = graph.NodesMap.delete(Number(node.id)) diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 12ad16f8..1e67f2dd 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -1,5 +1,5 @@ -import ForceGraph2D from 'react-force-graph-2d'; +import ForceGraph2D, { ForceGraphMethods } from 'react-force-graph-2d'; import { Graph, GraphData, Link, Node } from './model'; import { Dispatch, RefObject, SetStateAction, useEffect, useRef, useState } from 'react'; import { Path } from '../page'; @@ -13,7 +13,7 @@ interface Props { data: GraphData setData: Dispatch> graph: Graph - chartRef: RefObject + chartRef: React.MutableRefObject> selectedObj: Node | Link | undefined setSelectedObj: Dispatch> selectedObjects: Node[] diff --git a/app/components/toolbar.tsx b/app/components/toolbar.tsx index f718d741..463f1b64 100644 --- a/app/components/toolbar.tsx +++ b/app/components/toolbar.tsx @@ -1,9 +1,11 @@ import { CircleDot, Minus, Plus } from "lucide-react"; import { cn } from "@/lib/utils" -import { RefObject } from "react"; +import { ForceGraphMethods } from "react-force-graph-2d"; +import { Node, Link } from "./model"; +import { MutableRefObject } from "react"; interface Props { - chartRef: RefObject + chartRef: MutableRefObject> className?: string } From b029b548cf048cadc7572f4188f6d59dd6624988 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Sun, 16 Feb 2025 14:26:57 +0200 Subject: [PATCH 049/189] fix canvas test --- e2e/config/testData.ts | 7 ++++++- e2e/tests/canvas.spec.ts | 11 +++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/e2e/config/testData.ts b/e2e/config/testData.ts index 3cb008e2..34ba0a15 100644 --- a/e2e/config/testData.ts +++ b/e2e/config/testData.ts @@ -26,4 +26,9 @@ export const nodes: { nodeName: string; }[] = [ { nodeName: "list_graphs"} ]; -export const categories: string[] = ['File', 'Class', 'Function']; \ No newline at end of file +export const categories: string[] = ['File', 'Class', 'Function']; + +export const graphs: { graphName: string; }[] = [ + { graphName: "GraphRAG-SDK" }, + { graphName: "click" }, +]; \ No newline at end of file diff --git a/e2e/tests/canvas.spec.ts b/e2e/tests/canvas.spec.ts index e54858d8..108c9369 100644 --- a/e2e/tests/canvas.spec.ts +++ b/e2e/tests/canvas.spec.ts @@ -4,7 +4,7 @@ import CodeGraph from "../logic/POM/codeGraph"; import urls from "../config/urls.json"; import { GRAPH_ID, PROJECT_NAME } from "../config/constants"; import { findNodeByName } from "../logic/utils"; -import { nodesPath, categories, nodes } from "../config/testData"; +import { nodesPath, categories, nodes, graphs } from "../config/testData"; import { ApiCalls } from "../logic/api/apiCalls"; test.describe("Canvas tests", () => { @@ -117,16 +117,15 @@ test.describe("Canvas tests", () => { }); }) - for (let index = 0; index < 2; index++) { - const checkboxIndex = index + 1; - test(`Verify selecting different graphs displays nodes in canvas - Iteration ${index + 1}`, async () => { + graphs.forEach(({graphName}) => { + test(`Verify selecting different graphs displays nodes in canvas - grpah: ${graphName}`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(checkboxIndex); + await codeGraph.selectGraph(graphName); const result = await codeGraph.getGraphDetails(); expect(result.elements.nodes.length).toBeGreaterThan(1); expect(result.elements.links.length).toBeGreaterThan(1); }); - } + }) for (let index = 0; index < 3; index++) { const nodeIndex: number = index + 1; From a9fd8d81809b14d4785d9d051becdf7912cf2f88 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Sun, 16 Feb 2025 16:20:27 +0200 Subject: [PATCH 050/189] Update codeGraph.ts --- e2e/logic/POM/codeGraph.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 7cc9ccd7..82eec80a 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -476,14 +476,6 @@ export default class CodeGraph extends BasePage { throw new Error("Tooltip not visible after multiple attempts!"); } - - async nodeClicktest(x: number, y: number): Promise { - console.log(`Clicking node at (${x}, ${y})`); - await this.page.waitForTimeout(500); - await this.canvasElement.hover({ position: { x, y } }); - await this.canvasElement.click({ position: { x, y }, button: 'right' }); - await this.page.waitForTimeout(5000); - } async selectCodeGraphCheckbox(checkbox: string): Promise { await this.codeGraphCheckbox(checkbox).click(); From d14479ab20ad78b13929823ccfcb54e95b6550ee Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Sun, 16 Feb 2025 16:20:34 +0200 Subject: [PATCH 051/189] commit --- app/components/code-graph.tsx | 45 ++--- app/globals.css | 24 +++ app/page.tsx | 159 +++++++++++++---- components.json | 8 +- components/ui/carousel.tsx | 262 ++++++++++++++++++++++++++++ components/ui/drawer.tsx | 118 +++++++++++++ package-lock.json | 311 +++++++++++++++++++++++++--------- package.json | 12 +- tailwind.config.js | 149 ++++++++-------- 9 files changed, 876 insertions(+), 212 deletions(-) create mode 100644 components/ui/carousel.tsx create mode 100644 components/ui/drawer.tsx diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 9431cc2c..6d08c85a 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -33,6 +33,13 @@ interface Props { setSelectedPathId: (selectedPathId: number) => void isPathResponse: boolean | undefined setIsPathResponse: Dispatch> + handleSearchSubmit: (node: any) => void + searchNode: any + setSearchNode: Dispatch> + cooldownTicks: number | undefined + setCooldownTicks: Dispatch> + cooldownTime: number + setCooldownTime: Dispatch> } export function CodeGraph({ @@ -50,7 +57,14 @@ export function CodeGraph({ setSelectedPathId, isPathResponse, setIsPathResponse, - selectedPathId + selectedPathId, + handleSearchSubmit, + searchNode, + setSearchNode, + cooldownTicks, + setCooldownTicks, + cooldownTime, + setCooldownTime }: Props) { const [url, setURL] = useState(""); @@ -58,14 +72,11 @@ export function CodeGraph({ const [selectedObjects, setSelectedObjects] = useState([]); const [position, setPosition] = useState(); const [graphName, setGraphName] = useState(""); - const [searchNode, setSearchNode] = useState({}); const [commits, setCommits] = useState([]); const [nodesCount, setNodesCount] = useState(0); const [edgesCount, setEdgesCount] = useState(0); const [commitIndex, setCommitIndex] = useState(0); const [currentCommit, setCurrentCommit] = useState(0); - const [cooldownTicks, setCooldownTicks] = useState(0) - const [cooldownTime, setCooldownTime] = useState(0) const containerRef = useRef(null); useEffect(() => { @@ -223,32 +234,6 @@ export function CodeGraph({ setData({ ...graph.Elements }) } - const handleSearchSubmit = (node: any) => { - const chart = chartRef.current - - if (chart) { - - let chartNode = graph.Elements.nodes.find(n => n.id == node.id) - - if (!chartNode?.visible) { - if (!chartNode) { - chartNode = graph.extend({ nodes: [node], edges: [] }).nodes[0] - } else { - chartNode.visible = true - setCooldownTicks(undefined) - setCooldownTime(1000) - } - graph.visibleLinks(true, [chartNode!.id]) - setData({ ...graph.Elements }) - } - - setSearchNode(chartNode) - setTimeout(() => { - chart.zoomToFit(1000, 150, (n: NodeObject) => n.id === chartNode!.id); - }, 0) - } - } - const handleRemove = (ids: number[]) => { graph.Elements.nodes.forEach(node => { if (!ids.includes(node.id)) return diff --git a/app/globals.css b/app/globals.css index 51fd8ab8..ea80754a 100644 --- a/app/globals.css +++ b/app/globals.css @@ -33,6 +33,16 @@ --ring: 222.2 84% 4.9%; --radius: 0.5rem; + + --chart-1: 12 76% 61%; + + --chart-2: 173 58% 39%; + + --chart-3: 197 37% 24%; + + --chart-4: 43 74% 66%; + + --chart-5: 27 87% 67%; } .dark { @@ -64,6 +74,11 @@ --input: 217.2 32.6% 17.5%; --ring: 212.7 26.8% 83.9%; --radius: 0.5rem; + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; } } @@ -120,4 +135,13 @@ ::-webkit-scrollbar-thumb:hover { background-color: #a8bbbf; +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } } \ No newline at end of file diff --git a/app/page.tsx b/app/page.tsx index 7e37b205..5f2317f3 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -3,7 +3,7 @@ import { useEffect, useRef, useState } from 'react'; import { Chat } from './components/chat'; import { Graph, GraphData } from './components/model'; -import { BookOpen, Github, HomeIcon, X } from 'lucide-react'; +import { BookOpen, Github, HomeIcon, Search, X } from 'lucide-react'; import Link from 'next/link'; import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels"; import { CodeGraph } from './components/code-graph'; @@ -12,6 +12,10 @@ import { GraphContext } from './components/provider'; import Image from 'next/image'; import { DropdownMenu, DropdownMenuContent, DropdownMenuLabel, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'; import { prepareArg } from './utils'; +import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from '@/components/ui/carousel'; +import { Drawer, DrawerContent, DrawerTrigger } from '@/components/ui/drawer'; +import Input from './components/Input'; +import { NodeObject } from 'react-force-graph-2d'; export type PathNode = { id?: number @@ -63,6 +67,10 @@ export default function Home() { const [path, setPath] = useState(); const [isSubmit, setIsSubmit] = useState(false); const chartRef = useRef() + const [menuOpen, setMenuOpen] = useState(false) + const [searchNode, setSearchNode] = useState({}); + const [cooldownTicks, setCooldownTicks] = useState(0) + const [cooldownTime, setCooldownTime] = useState(0) useEffect(() => { setIsPathResponse(false) @@ -158,6 +166,32 @@ export default function Home() { return graph.extend(json.result.neighbors, true) } + const handleSearchSubmit = (node: any) => { + const chart = chartRef.current + + if (chart) { + + let chartNode = graph.Elements.nodes.find(n => n.id == node.id) + + if (!chartNode?.visible) { + if (!chartNode) { + chartNode = graph.extend({ nodes: [node], edges: [] }).nodes[0] + } else { + chartNode.visible = true + setCooldownTicks(undefined) + setCooldownTime(1000) + } + graph.visibleLinks(true, [chartNode!.id]) + setData({ ...graph.Elements }) + } + + setSearchNode(chartNode) + setTimeout(() => { + chart.zoomToFit(1000, 150, (n: NodeObject) => n.id === chartNode!.id); + }, 0) + } + } + return (
@@ -276,6 +310,13 @@ export default function Home() { setSelectedPathId={setSelectedPathId} isPathResponse={isPathResponse} setIsPathResponse={setIsPathResponse} + handleSearchSubmit={handleSearchSubmit} + searchNode={searchNode} + setSearchNode={setSearchNode} + cooldownTicks={cooldownTicks} + setCooldownTicks={setCooldownTicks} + cooldownTime={cooldownTime} + setCooldownTime={setCooldownTime} /> @@ -297,39 +338,99 @@ export default function Home() {
FalkorDB -
- { - graph.Id && -
- - -
+ menuOpen ? +
    +
  • + +

    Github

    + +
  • +
  • + +

    Discord

    + +
  • +
  • + +

    Main Website

    + +
  • + + + +

    Item 1

    +
    + +

    Item 2

    +
    +
    + + +
    +
+ : <> + + { + graph.Id && +
+ + + + + + + setSearchNode(node)} + icon={} + handleSubmit={handleSearchSubmit} + node={searchNode} + /> + + +
+ } + }
-
+ ) } diff --git a/components.json b/components.json index 811d2dbc..05fa7462 100644 --- a/components.json +++ b/components.json @@ -12,6 +12,10 @@ }, "aliases": { "components": "@/components", - "utils": "@/lib/utils" - } + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "iconLibrary": "lucide" } \ No newline at end of file diff --git a/components/ui/carousel.tsx b/components/ui/carousel.tsx new file mode 100644 index 00000000..2e34403b --- /dev/null +++ b/components/ui/carousel.tsx @@ -0,0 +1,262 @@ +"use client" + +import * as React from "react" +import useEmblaCarousel, { + type UseEmblaCarouselType, +} from "embla-carousel-react" +import { ArrowLeft, ArrowRight } from "lucide-react" + +import { cn } from "@/lib/utils" +import { Button } from "@/components/ui/button" + +type CarouselApi = UseEmblaCarouselType[1] +type UseCarouselParameters = Parameters +type CarouselOptions = UseCarouselParameters[0] +type CarouselPlugin = UseCarouselParameters[1] + +type CarouselProps = { + opts?: CarouselOptions + plugins?: CarouselPlugin + orientation?: "horizontal" | "vertical" + setApi?: (api: CarouselApi) => void +} + +type CarouselContextProps = { + carouselRef: ReturnType[0] + api: ReturnType[1] + scrollPrev: () => void + scrollNext: () => void + canScrollPrev: boolean + canScrollNext: boolean +} & CarouselProps + +const CarouselContext = React.createContext(null) + +function useCarousel() { + const context = React.useContext(CarouselContext) + + if (!context) { + throw new Error("useCarousel must be used within a ") + } + + return context +} + +const Carousel = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes & CarouselProps +>( + ( + { + orientation = "horizontal", + opts, + setApi, + plugins, + className, + children, + ...props + }, + ref + ) => { + const [carouselRef, api] = useEmblaCarousel( + { + ...opts, + axis: orientation === "horizontal" ? "x" : "y", + }, + plugins + ) + const [canScrollPrev, setCanScrollPrev] = React.useState(false) + const [canScrollNext, setCanScrollNext] = React.useState(false) + + const onSelect = React.useCallback((api: CarouselApi) => { + if (!api) { + return + } + + setCanScrollPrev(api.canScrollPrev()) + setCanScrollNext(api.canScrollNext()) + }, []) + + const scrollPrev = React.useCallback(() => { + api?.scrollPrev() + }, [api]) + + const scrollNext = React.useCallback(() => { + api?.scrollNext() + }, [api]) + + const handleKeyDown = React.useCallback( + (event: React.KeyboardEvent) => { + if (event.key === "ArrowLeft") { + event.preventDefault() + scrollPrev() + } else if (event.key === "ArrowRight") { + event.preventDefault() + scrollNext() + } + }, + [scrollPrev, scrollNext] + ) + + React.useEffect(() => { + if (!api || !setApi) { + return + } + + setApi(api) + }, [api, setApi]) + + React.useEffect(() => { + if (!api) { + return + } + + onSelect(api) + api.on("reInit", onSelect) + api.on("select", onSelect) + + return () => { + api?.off("select", onSelect) + } + }, [api, onSelect]) + + return ( + +
+ {children} +
+
+ ) + } +) +Carousel.displayName = "Carousel" + +const CarouselContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => { + const { carouselRef, orientation } = useCarousel() + + return ( +
+
+
+ ) +}) +CarouselContent.displayName = "CarouselContent" + +const CarouselItem = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => { + const { orientation } = useCarousel() + + return ( +
+ ) +}) +CarouselItem.displayName = "CarouselItem" + +const CarouselPrevious = React.forwardRef< + HTMLButtonElement, + React.ComponentProps +>(({ className, variant = "outline", size = "icon", ...props }, ref) => { + const { orientation, scrollPrev, canScrollPrev } = useCarousel() + + return ( + + ) +}) +CarouselPrevious.displayName = "CarouselPrevious" + +const CarouselNext = React.forwardRef< + HTMLButtonElement, + React.ComponentProps +>(({ className, variant = "outline", size = "icon", ...props }, ref) => { + const { orientation, scrollNext, canScrollNext } = useCarousel() + + return ( + + ) +}) +CarouselNext.displayName = "CarouselNext" + +export { + type CarouselApi, + Carousel, + CarouselContent, + CarouselItem, + CarouselPrevious, + CarouselNext, +} diff --git a/components/ui/drawer.tsx b/components/ui/drawer.tsx new file mode 100644 index 00000000..6a0ef53d --- /dev/null +++ b/components/ui/drawer.tsx @@ -0,0 +1,118 @@ +"use client" + +import * as React from "react" +import { Drawer as DrawerPrimitive } from "vaul" + +import { cn } from "@/lib/utils" + +const Drawer = ({ + shouldScaleBackground = true, + ...props +}: React.ComponentProps) => ( + +) +Drawer.displayName = "Drawer" + +const DrawerTrigger = DrawerPrimitive.Trigger + +const DrawerPortal = DrawerPrimitive.Portal + +const DrawerClose = DrawerPrimitive.Close + +const DrawerOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName + +const DrawerContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + +
+ {children} + + +)) +DrawerContent.displayName = "DrawerContent" + +const DrawerHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DrawerHeader.displayName = "DrawerHeader" + +const DrawerFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DrawerFooter.displayName = "DrawerFooter" + +const DrawerTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DrawerTitle.displayName = DrawerPrimitive.Title.displayName + +const DrawerDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DrawerDescription.displayName = DrawerPrimitive.Description.displayName + +export { + Drawer, + DrawerPortal, + DrawerOverlay, + DrawerTrigger, + DrawerClose, + DrawerContent, + DrawerHeader, + DrawerFooter, + DrawerTitle, + DrawerDescription, +} diff --git a/package-lock.json b/package-lock.json index 11fe98ce..d74f94fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,19 +9,20 @@ "version": "0.2.0", "dependencies": { "@radix-ui/react-checkbox": "^1.1.2", - "@radix-ui/react-dialog": "^1.1.2", + "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dropdown-menu": "^2.1.2", "@radix-ui/react-hover-card": "^1.1.2", "@radix-ui/react-progress": "^1.1.0", "@radix-ui/react-select": "^2.1.2", - "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-slot": "^1.1.2", "@radix-ui/react-toast": "^1.2.2", "@radix-ui/react-tooltip": "^1.1.4", "@types/react-gtm-module": "^2.0.4", "autoprefixer": "^10.4.20", "canvas2svg": "^1.0.16", "class-variance-authority": "^0.7.1", - "clsx": "^2.1.0", + "clsx": "^2.1.1", + "embla-carousel-react": "^8.5.2", "html2canvas": "^1.4.1", "lucide-react": "^0.441.0", "next": "^15.1.2", @@ -34,8 +35,9 @@ "react-resizable-panels": "^2.0.20", "react-syntax-highlighter": "^15.6.1", "react-type-animation": "^3.2.0", - "tailwind-merge": "^2.5.5", - "tailwindcss-animate": "^1.0.7" + "tailwind-merge": "^2.6.0", + "tailwindcss-animate": "^1.0.7", + "vaul": "^1.1.2" }, "devDependencies": { "@playwright/test": "^1.49.1", @@ -1076,6 +1078,23 @@ } } }, + "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-compose-refs": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", @@ -1107,24 +1126,24 @@ } }, "node_modules/@radix-ui/react-dialog": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.2.tgz", - "integrity": "sha512-Yj4dZtqa2o+kG61fzB0H2qUvmwBA2oyQroGLyNtBj1beo1khoQ3q1a2AO8rrQYjd8256CO9+N8L9tvsS+bnIyA==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.6.tgz", + "integrity": "sha512-/IVhJV5AceX620DUJ4uYVMymzsipdKBzo3edo+omeskCKGm9FRHM0ebIdbPnlQVJqyuHbuBltQUOG2mOTq2IYw==", "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.5", "@radix-ui/react-focus-guards": "1.1.1", - "@radix-ui/react-focus-scope": "1.1.0", + "@radix-ui/react-focus-scope": "1.1.2", "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-portal": "1.1.2", - "@radix-ui/react-presence": "1.1.1", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-slot": "1.1.0", + "@radix-ui/react-portal": "1.1.4", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-slot": "1.1.2", "@radix-ui/react-use-controllable-state": "1.1.0", - "aria-hidden": "^1.1.1", - "react-remove-scroll": "2.6.0" + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", @@ -1141,6 +1160,25 @@ } } }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", + "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==" + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", + "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-context": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", @@ -1156,13 +1194,13 @@ } }, "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz", - "integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz", + "integrity": "sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg==", "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-escape-keydown": "1.1.0" }, @@ -1181,13 +1219,14 @@ } } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-portal": { + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-scope": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz", - "integrity": "sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz", + "integrity": "sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA==", "dependencies": { - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "*", @@ -1204,12 +1243,12 @@ } } }, - "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-presence": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz", - "integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-portal": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.4.tgz", + "integrity": "sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA==", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { @@ -1227,6 +1266,52 @@ } } }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-primitive": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz", + "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==", + "dependencies": { + "@radix-ui/react-slot": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz", + "integrity": "sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-direction": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", @@ -1666,6 +1751,23 @@ } } }, + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-popper": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz", @@ -1834,6 +1936,23 @@ } } }, + "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-progress": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.0.tgz", @@ -2104,13 +2223,26 @@ } }, "node_modules/@radix-ui/react-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", - "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", - "license": "MIT", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", + "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0" + "@radix-ui/react-compose-refs": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", + "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -3576,7 +3708,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", "engines": { "node": ">=6" } @@ -4067,6 +4198,31 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.63.tgz", "integrity": "sha512-ddeXKuY9BHo/mw145axlyWjlJ1UBt4WK3AlvkT7W2AbqfRQoacVoRUCF6wL3uIx/8wT9oLKXzI+rFqHHscByaA==" }, + "node_modules/embla-carousel": { + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.5.2.tgz", + "integrity": "sha512-xQ9oVLrun/eCG/7ru3R+I5bJ7shsD8fFwLEY7yPe27/+fDHCNj0OT5EoG5ZbFyOxOcG6yTwW8oTz/dWyFnyGpg==" + }, + "node_modules/embla-carousel-react": { + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/embla-carousel-react/-/embla-carousel-react-8.5.2.tgz", + "integrity": "sha512-Tmx+uY3MqseIGdwp0ScyUuxpBgx5jX1f7od4Cm5mDwg/dptEiTKf9xp6tw0lZN2VA9JbnVMl/aikmbc53c6QFA==", + "dependencies": { + "embla-carousel": "8.5.2", + "embla-carousel-reactive-utils": "8.5.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.1 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, + "node_modules/embla-carousel-reactive-utils": { + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/embla-carousel-reactive-utils/-/embla-carousel-reactive-utils-8.5.2.tgz", + "integrity": "sha512-QC8/hYSK/pEmqEdU1IO5O+XNc/Ptmmq7uCB44vKplgLKhB/l0+yvYx0+Cv0sF6Ena8Srld5vUErZkT+yTahtDg==", + "peerDependencies": { + "embla-carousel": "8.5.2" + } + }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -5341,15 +5497,6 @@ "node": ">=12" } }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.0.0" - } - }, "node_modules/is-alphabetical": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", @@ -6901,20 +7048,19 @@ } }, "node_modules/react-remove-scroll-bar": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz", - "integrity": "sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==", - "license": "MIT", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", "dependencies": { - "react-style-singleton": "^2.2.1", + "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "engines": { "node": ">=10" }, "peerDependencies": { - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -6933,21 +7079,19 @@ } }, "node_modules/react-style-singleton": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", - "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==", - "license": "MIT", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", "dependencies": { "get-nonce": "^1.0.0", - "invariant": "^2.2.4", "tslib": "^2.0.0" }, "engines": { "node": ">=10" }, "peerDependencies": { - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { @@ -7706,9 +7850,9 @@ } }, "node_modules/tailwind-merge": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.5.tgz", - "integrity": "sha512-0LXunzzAZzo0tEPxV3I297ffKZPlKDrjj7NXphC8V5ak9yHC5zRmxnOe2m/Rd/7ivsOMJe3JZ2JVocoDdQTRBA==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.0.tgz", + "integrity": "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==", "funding": { "type": "github", "url": "https://github.com/sponsors/dcastil" @@ -7754,7 +7898,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", - "license": "MIT", "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } @@ -8017,10 +8160,9 @@ } }, "node_modules/use-callback-ref": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz", - "integrity": "sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==", - "license": "MIT", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", "dependencies": { "tslib": "^2.0.0" }, @@ -8028,8 +8170,8 @@ "node": ">=10" }, "peerDependencies": { - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { @@ -8038,10 +8180,9 @@ } }, "node_modules/use-sidecar": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", - "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==", - "license": "MIT", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" @@ -8050,8 +8191,8 @@ "node": ">=10" }, "peerDependencies": { - "@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { @@ -8073,6 +8214,18 @@ "base64-arraybuffer": "^1.0.2" } }, + "node_modules/vaul": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vaul/-/vaul-1.1.2.tgz", + "integrity": "sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA==", + "dependencies": { + "@radix-ui/react-dialog": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 7554b92c..fc48ef94 100644 --- a/package.json +++ b/package.json @@ -10,19 +10,20 @@ }, "dependencies": { "@radix-ui/react-checkbox": "^1.1.2", - "@radix-ui/react-dialog": "^1.1.2", + "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dropdown-menu": "^2.1.2", "@radix-ui/react-hover-card": "^1.1.2", "@radix-ui/react-progress": "^1.1.0", "@radix-ui/react-select": "^2.1.2", - "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-slot": "^1.1.2", "@radix-ui/react-toast": "^1.2.2", "@radix-ui/react-tooltip": "^1.1.4", "@types/react-gtm-module": "^2.0.4", "autoprefixer": "^10.4.20", "canvas2svg": "^1.0.16", "class-variance-authority": "^0.7.1", - "clsx": "^2.1.0", + "clsx": "^2.1.1", + "embla-carousel-react": "^8.5.2", "html2canvas": "^1.4.1", "lucide-react": "^0.441.0", "next": "^15.1.2", @@ -35,8 +36,9 @@ "react-resizable-panels": "^2.0.20", "react-syntax-highlighter": "^15.6.1", "react-type-animation": "^3.2.0", - "tailwind-merge": "^2.5.5", - "tailwindcss-animate": "^1.0.7" + "tailwind-merge": "^2.6.0", + "tailwindcss-animate": "^1.0.7", + "vaul": "^1.1.2" }, "devDependencies": { "@playwright/test": "^1.49.1", diff --git a/tailwind.config.js b/tailwind.config.js index 14d51792..bad191f5 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -14,73 +14,88 @@ module.exports = { ], prefix: "", theme: { - container: { - center: true, - padding: "2rem", - screens: { - "2xl": "1400px", - }, - }, - extend: { - colors: { - blue: "#7466FF", - pink: "#FF66B3", - orange: "#FF804D", - turquoise: "#80E6E6", - border: "hsl(var(--border))", - input: "hsl(var(--input))", - ring: "hsl(var(--ring))", - background: "hsl(var(--background))", - foreground: "hsl(var(--foreground))", - primary: { - DEFAULT: "hsl(var(--primary))", - foreground: "hsl(var(--primary-foreground))", - }, - secondary: { - DEFAULT: "hsl(var(--secondary))", - foreground: "hsl(var(--secondary-foreground))", - }, - destructive: { - DEFAULT: "hsl(var(--destructive))", - foreground: "hsl(var(--destructive-foreground))", - }, - muted: { - DEFAULT: "hsl(var(--muted))", - foreground: "hsl(var(--muted-foreground))", - }, - accent: { - DEFAULT: "hsl(var(--accent))", - foreground: "hsl(var(--accent-foreground))", - }, - popover: { - DEFAULT: "hsl(var(--popover))", - foreground: "hsl(var(--popover-foreground))", - }, - card: { - DEFAULT: "hsl(var(--card))", - foreground: "hsl(var(--card-foreground))", - }, - }, - borderRadius: { - lg: "var(--radius)", - md: "calc(var(--radius) - 2px)", - sm: "calc(var(--radius) - 4px)", - }, - keyframes: { - "accordion-down": { - from: { height: "0" }, - to: { height: "var(--radix-accordion-content-height)" }, - }, - "accordion-up": { - from: { height: "var(--radix-accordion-content-height)" }, - to: { height: "0" }, - }, - }, - animation: { - "accordion-down": "accordion-down 0.2s ease-out", - "accordion-up": "accordion-up 0.2s ease-out", - }, - }, + container: { + center: true, + padding: '2rem', + screens: { + '2xl': '1400px' + } + }, + extend: { + colors: { + blue: '#7466FF', + pink: '#FF66B3', + orange: '#FF804D', + turquoise: '#80E6E6', + border: 'hsl(var(--border))', + input: 'hsl(var(--input))', + ring: 'hsl(var(--ring))', + background: 'hsl(var(--background))', + foreground: 'hsl(var(--foreground))', + primary: { + DEFAULT: 'hsl(var(--primary))', + foreground: 'hsl(var(--primary-foreground))' + }, + secondary: { + DEFAULT: 'hsl(var(--secondary))', + foreground: 'hsl(var(--secondary-foreground))' + }, + destructive: { + DEFAULT: 'hsl(var(--destructive))', + foreground: 'hsl(var(--destructive-foreground))' + }, + muted: { + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))' + }, + accent: { + DEFAULT: 'hsl(var(--accent))', + foreground: 'hsl(var(--accent-foreground))' + }, + popover: { + DEFAULT: 'hsl(var(--popover))', + foreground: 'hsl(var(--popover-foreground))' + }, + card: { + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))' + }, + chart: { + '1': 'hsl(var(--chart-1))', + '2': 'hsl(var(--chart-2))', + '3': 'hsl(var(--chart-3))', + '4': 'hsl(var(--chart-4))', + '5': 'hsl(var(--chart-5))' + } + }, + borderRadius: { + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)' + }, + keyframes: { + 'accordion-down': { + from: { + height: '0' + }, + to: { + height: 'var(--radix-accordion-content-height)' + } + }, + 'accordion-up': { + from: { + height: 'var(--radix-accordion-content-height)' + }, + to: { + height: '0' + } + } + }, + animation: { + 'accordion-down': 'accordion-down 0.2s ease-out', + 'accordion-up': 'accordion-up 0.2s ease-out' + } + } }, plugins: [require("tailwindcss-animate")], } \ No newline at end of file From 750f2fdd447babcfb8d996466685dbf7061b15d3 Mon Sep 17 00:00:00 2001 From: danshalev7 Date: Sun, 16 Feb 2025 17:24:09 +0200 Subject: [PATCH 052/189] Update README.md --- README.md | 95 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index edd18fcb..6f31ed58 100644 --- a/README.md +++ b/README.md @@ -1,87 +1,118 @@ +# CodeGraph - Knowledge Graph Visualization Tool + +###Visualize your repository with our graph for code analysis + [![Try Free](https://img.shields.io/badge/Try%20Free-FalkorDB%20Cloud-FF8101?labelColor=FDE900&link=https://app.falkordb.cloud)](https://app.falkordb.cloud) [![Dockerhub](https://img.shields.io/docker/pulls/falkordb/falkordb?label=Docker)](https://hub.docker.com/r/falkordb/falkordb/) [![Discord](https://img.shields.io/discord/1146782921294884966?style=flat-square)](https://discord.com/invite/6M4QwDXn2w) [![Workflow](https://github.com/FalkorDB/code-graph/actions/workflows/nextjs.yml/badge.svg?branch=main)](https://github.com/FalkorDB/code-graph/actions/workflows/nextjs.yml) +- + +![Alt Text](https://res.cloudinary.com/dhd0k02an/image/upload/v1739719361/FalkorDB_-_Github_-_readme_jr6scy.gif) + + + +**👉🏻[Live Demo](https://code-graph.falkordb.com/)** + -![image](https://github.com/FalkorDB/code-graph/assets/753206/60f535ed-cf29-44b2-9005-721f11614803) -## Getting Started -[Live Demo](https://code-graph.falkordb.com/) +## Running Locally -## Run locally -This project is composed of three pieces: +This project consists of three core components: -1. FalkorDB Graph DB - this is where your graphs are stored and queried -2. Code-Graph-Backend - backend logic -3. Code-Graph-Frontend - website +1. **FalkorDB Graph DB** – Stores and queries your graphs. +2. **Code-Graph-Backend** – Handles backend logic. +3. **Code-Graph-Frontend** – Provides the web interface. -You'll need to start all three components: +To set up the project, you’ll need to start all three components. -### Run FalkorDB +### 1. Start FalkorDB + +Run the following command to start FalkorDB using Docker: ```bash docker run -p 6379:6379 -it --rm falkordb/falkordb ``` -### Run Code-Graph-Backend +### 2. Start the Backend -#### Clone the Backend +#### Clone the Backend Repository ```bash git clone https://github.com/FalkorDB/code-graph-backend.git +cd code-graph-backend ``` -#### Setup environment variables +#### Set Up Environment Variables -`SECRET_TOKEN` - user defined token used to authorize the request +Define the required environment variables: ```bash export FALKORDB_HOST=localhost FALKORDB_PORT=6379 \ - OPENAI_API_KEY= SECRET_TOKEN= \ + OPENAI_API_KEY= SECRET_TOKEN= \ FLASK_RUN_HOST=0.0.0.0 FLASK_RUN_PORT=5000 ``` -#### Install dependencies & run +`SECRET_TOKEN` is a user-defined token used for request authorization. -```bash -cd code-graph-backend +#### Install Dependencies & Start the Backend +```bash pip install --no-cache-dir -r requirements.txt - flask --app api/index.py run --debug > flask.log 2>&1 & - ``` -### Run Code-Graph-Frontend +### 3. Start the Frontend -#### Clone the Frontend +#### Clone the Frontend Repository ```bash git clone https://github.com/FalkorDB/code-graph.git +cd code-graph ``` -#### Setup environment variables +#### Set Up Environment Variables ```bash export BACKEND_URL=http://${FLASK_RUN_HOST}:${FLASK_RUN_PORT} \ - SECRET_TOKEN= OPENAI_API_KEY= + SECRET_TOKEN= OPENAI_API_KEY= ``` -#### Install dependencies & run +#### Install Dependencies & Start the Frontend ```bash -cd code-graph npm install npm run dev ``` -### Process a local repository +### 4. Process a Local Repository + +Use the following `curl` command to analyze a local repository: + ```bash -curl -X POST http://127.0.0.1:5000/analyze_folder -H "Content-Type: application/json" -d '{"path": "", "ignore": ["./.github", "./sbin", "./.git","./deps", "./bin", "./build"]}' -H "Authorization: " +curl -X POST http://127.0.0.1:5000/analyze_folder \ + -H "Content-Type: application/json" \ + -H "Authorization: " \ + -d '{"path": "", "ignore": ["./.github", "./sbin", "./.git", "./deps", "./bin", "./build"]}' ``` -Note: At the moment code-graph can analyze both the C & Python source files. -Support for additional languages e.g. JavaScript, Go, Java is planned to be added -in the future. +**Note:** Currently, Code-Graph supports analyzing C and Python source files. +Support for additional languages (e.g., JavaScript, Go, Java) is planned. + +### 5. Access the Web Interface + +Once everything is running, open your browser and go to: + +[http://localhost:3000](http://localhost:3000) + + + +## Community +Have questions or feedback? Reach out via: + +* [GitHub Issues](https://github.com/FalkorDB/GraphRAG-SDK/issues) +* Join our [Discord](https://discord.com/invite/6M4QwDXn2w) + +⭐️ If you find this repository helpful, please consider giving it a star! -Browse to [http://localhost:3000](http://localhost:3000) +Knowledge Graph, Code Analysis, Code Visualization, Dead Code Analysis, Graph Database From 341f2720603b1ea5f81d7129c82f7c7b8f9ff23c Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Mon, 17 Feb 2025 10:58:14 +0200 Subject: [PATCH 053/189] commit --- app/api/repo/route.ts | 2 +- app/page.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/api/repo/route.ts b/app/api/repo/route.ts index 8fb38dec..421be274 100644 --- a/app/api/repo/route.ts +++ b/app/api/repo/route.ts @@ -40,7 +40,7 @@ export async function POST(request: NextRequest) { const isLocal = repo_url.startsWith("file://") - const result = await fetch(`${url}/${isLocal ? "analyze_folder" : "process_repo"}`, { + const result = await fetch(`${url}/${isLocal ? "analyze_folder" : "analyze_repo"}`, { method: 'POST', body: JSON.stringify({ repo_url, ignore: ["./.github", "./sbin", "./.git", "./deps", "./bin", "./build"] }), headers: { diff --git a/app/page.tsx b/app/page.tsx index f6670b3d..3c9e5da8 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -236,7 +236,7 @@ export default function Home() { { !isSubmit ? -
+ Date: Wed, 19 Feb 2025 13:51:15 +0200 Subject: [PATCH 054/189] commit --- app/components/Input.tsx | 3 +- app/components/chat.tsx | 219 +++++++-------------- app/components/code-graph.tsx | 57 +----- app/components/graphView.tsx | 8 +- app/components/toolbar.tsx | 26 +-- app/globals.css | 18 +- app/page.tsx | 327 +++++++++++++++++++++++-------- components/ui/drawer.tsx | 13 +- lib/utils.ts | 30 ++- package-lock.json | 355 ++++++++++++++++++++++++++++++---- package.json | 2 + public/code-graph-logo.svg | 33 ++++ 12 files changed, 738 insertions(+), 353 deletions(-) create mode 100644 public/code-graph-logo.svg diff --git a/app/components/Input.tsx b/app/components/Input.tsx index 9ab6da79..a2f29a9e 100644 --- a/app/components/Input.tsx +++ b/app/components/Input.tsx @@ -133,7 +133,7 @@ export default function Input({ onValueChange, handleSubmit, graph, icon, node, return (
{ const newVal = e.target.value diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 6af9ac79..611abefc 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -1,8 +1,8 @@ import { toast } from "@/components/ui/use-toast"; import { Dispatch, FormEvent, SetStateAction, useEffect, useRef, useState } from "react"; import Image from "next/image"; -import { AlignLeft, ArrowDown, ArrowRight, ChevronDown, Lightbulb, Undo2 } from "lucide-react"; -import { Path } from "../page"; +import { AlignLeft, ArrowRight, ChevronDown, Lightbulb, Undo2 } from "lucide-react"; +import { Message, MessageTypes, Path, PathData } from "../page"; import Input from "./Input"; import { Graph, GraphData } from "./model"; import { cn } from "@/lib/utils"; @@ -11,71 +11,6 @@ import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from "@/compon import { prepareArg } from "../utils"; import { NodeObject } from "react-force-graph-2d"; -type PathData = { - nodes: any[] - links: any[] -} - -enum MessageTypes { - Query, - Response, - Path, - PathResponse, - Pending, - Text, -} - -const EDGE_STYLE = { - "line-color": "gray", - "target-arrow-color": "gray", - "opacity": 0.5, -} - - -const PATH_EDGE_STYLE = { - width: 0.5, - "line-style": "dashed", - "line-color": "#FF66B3", - "arrow-scale": 0.3, - "target-arrow-color": "#FF66B3", - "opacity": 1 -} - -const SELECTED_PATH_EDGE_STYLE = { - width: 1, - "line-style": "solid", - "line-color": "#FF66B3", - "arrow-scale": 0.6, - "target-arrow-color": "#FF66B3", -}; - -const NODE_STYLE = { - "border-width": 0.5, - "color": "gray", - "border-color": "black", - "background-color": "gray", - "opacity": 0.5 -} - -const PATH_NODE_STYLE = { - "border-width": 0.5, - "border-color": "#FF66B3", - "border-opacity": 1, -} - -const SELECTED_PATH_NODE_STYLE = { - "border-width": 1, - "border-color": "#FF66B3", - "border-opacity": 1, -}; - -interface Message { - type: MessageTypes; - text?: string; - paths?: { nodes: any[], links: any[] }[]; - graphName?: string; -} - interface Props { repo: string path: Path | undefined @@ -86,6 +21,15 @@ interface Props { setIsPathResponse: (isPathResponse: boolean | undefined) => void setData: Dispatch> chartRef: any + messages: Message[] + setMessages: Dispatch> + query: string + setQuery: Dispatch> + selectedPath: PathData | undefined + setSelectedPath: Dispatch> + setChatOpen?: Dispatch> + paths: PathData[] + setPaths: Dispatch> } const SUGGESTIONS = [ @@ -107,20 +51,7 @@ const RemoveLastPath = (messages: Message[]) => { return messages } -export function Chat({ repo, path, setPath, graph, selectedPathId, isPathResponse, setIsPathResponse, setData, chartRef }: Props) { - - // Holds the messages in the chat - const [messages, setMessages] = useState([]); - - // Holds the messages in the chat - const [paths, setPaths] = useState([]); - - const [selectedPath, setSelectedPath] = useState(); - - // Holds the user input while typing - const [query, setQuery] = useState(''); - - const [tipOpen, setTipOpen] = useState(false); +export function Chat({ messages, setMessages, query, setQuery, selectedPath, setSelectedPath, setChatOpen, repo, path, setPath, graph, selectedPathId, isPathResponse, setIsPathResponse, setData, chartRef, paths, setPaths }: Props) { const [sugOpen, setSugOpen] = useState(false); @@ -138,9 +69,14 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons // Scroll to the bottom of the chat on new message useEffect(() => { - setTimeout(() => { + if (messages.length === 0) return + const timeout = setTimeout(() => { containerRef.current?.scrollTo(0, containerRef.current?.scrollHeight); }, 300) + + return () => { + clearTimeout(timeout) + } }, [messages]); useEffect(() => { @@ -156,7 +92,7 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons const handleSetSelectedPath = (p: PathData) => { const chart = chartRef.current - + if (!chart) return setSelectedPath(prev => { if (prev) { @@ -213,6 +149,7 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons setTimeout(() => { chart.zoomToFit(1000, 150, (n: NodeObject) => p.nodes.some(node => node.id === n.id)); }, 0) + setChatOpen && setChatOpen(false) } // A function that handles the change event of the url input box @@ -274,9 +211,11 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons if (!chart) return setSelectedPath(undefined) - + if (!path?.start?.id || !path.end?.id) return - + + setPath(undefined) + const result = await fetch(`/api/repo/${prepareArg(repo)}/${prepareArg(String(path.start.id))}/?targetId=${prepareArg(String(path.end.id))}`, { method: 'POST' }) @@ -305,7 +244,6 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons setPaths(formattedPaths) setMessages((prev) => [...RemoveLastPath(prev), { type: MessageTypes.PathResponse, paths: formattedPaths, graphName: graph.Id }]); - setPath(undefined) setIsPathResponse(true) setData({ ...graph.Elements }) setTimeout(() => { @@ -313,13 +251,13 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons }, 0) } - const getTip = (disabled = false) => + const getTip = (className?: string) => <> + { + SUGGESTIONS.map((s, i) => ( + + )) + } const getMessage = (message: Message, index?: number) => { @@ -434,10 +384,10 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons } if (selectedPath?.nodes.every(node => p?.nodes.some((n) => n.id === node.id)) && selectedPath.nodes.length === p.nodes.length) return - + if (!isPathResponse) { setIsPathResponse(undefined) - + } handleSetSelectedPath(p) }} @@ -464,18 +414,15 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons } return ( -
+
{ messages.length === 0 && <> -

WELCOME TO OUR ASSISTANCE SERVICE

- - We can help you access and update only the needed - data via paths, optimizing network requests with - batching and catching for better performance. - - {getTip()} +

What would you like to analyze?

+
+ {getTip()} +
} { @@ -483,54 +430,28 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons return getMessage(message, index) }) } - { - tipOpen && -
ref?.focus()} className="bg-white absolute bottom-24 border rounded-md flex flex-col gap-3 p-2 overflow-y-auto" tabIndex={-1} onMouseDown={(e) => e.preventDefault()} onBlur={() => setTipOpen(false)}> - {getTip(isSendMessage)} -
- }
- -
- { - repo && -
- - - - - - - - -
- } + + + {getTip("!w-full")} + + +
+ + +
- - { - SUGGESTIONS.map((s, i) => ( - - )) - } - -
+ }
); } diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 6d08c85a..1c5b3b2c 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -13,7 +13,6 @@ import { Checkbox } from '@/components/ui/checkbox'; import dynamic from 'next/dynamic'; import { Position } from "./graphView"; import { prepareArg } from '../utils'; -import { NodeObject } from "react-force-graph-2d"; const GraphView = dynamic(() => import('./graphView')); @@ -40,6 +39,8 @@ interface Props { setCooldownTicks: Dispatch> cooldownTime: number setCooldownTime: Dispatch> + onCategoryClick: (name: string, show: boolean) => void + handleDownloadImage: () => void } export function CodeGraph({ @@ -64,7 +65,9 @@ export function CodeGraph({ cooldownTicks, setCooldownTicks, cooldownTime, - setCooldownTime + setCooldownTime, + onCategoryClick, + handleDownloadImage }: Props) { const [url, setURL] = useState(""); @@ -163,19 +166,6 @@ export function CodeGraph({ onFetchGraph(value) } - function onCategoryClick(name: string, show: boolean) { - graph.Categories.find(c => c.name === name)!.show = show - - graph.Elements.nodes.forEach(node => { - if (!(node.category === name)) return - node.visible = show - }) - - graph.visibleLinks(show) - - setData({ ...graph.Elements }) - } - const deleteNeighbors = (nodes: Node[]) => { if (nodes.length === 0) return; @@ -245,35 +235,8 @@ export function CodeGraph({ setData({ ...graph.Elements }) } - const handleDownloadImage = async () => { - try { - const canvas = document.querySelector('.force-graph-container canvas') as HTMLCanvasElement; - if (!canvas) { - toast({ - title: "Error", - description: "Canvas not found", - variant: "destructive", - }); - return; - } - - const dataURL = canvas.toDataURL('image/webp'); - const link = document.createElement('a'); - link.href = dataURL; - link.download = `${graphName}.webp`; - link.click(); - } catch (error) { - console.error('Error downloading graph image:', error); - toast({ - title: "Error", - description: "Failed to download image. Please try again.", - variant: "destructive", - }); - } - }; - return ( -
+
-
-
+
+
setSearchNode(node)} @@ -398,11 +361,11 @@ export function CodeGraph({
}
+ chartRef: MutableRefObject | undefined> className?: string } export function Toolbar({ chartRef, className }: Props) { const handleZoomClick = (changefactor: number) => { + debugger const chart = chartRef.current if (chart) { chart.zoom(chart.zoom() * changefactor) @@ -17,34 +19,36 @@ export function Toolbar({ chartRef, className }: Props) { } const handleCenterClick = () => { + debugger const chart = chartRef.current if (chart) { + console.log(chart.getGraphBbox()) chart.zoomToFit(1000, 40) } } return ( -
+
) diff --git a/app/globals.css b/app/globals.css index ea80754a..e1f3eb46 100644 --- a/app/globals.css +++ b/app/globals.css @@ -94,19 +94,7 @@ } .Tip { - @apply flex gap-2 p-4 border border-[#0000001A] bg-[#F9F9F9] hover:bg-[#ECECEC] rounded-md text-left; - - .label { - @apply text-[16px] font-bold leading-[14px] - } - - .text { - @apply text-[16px] font-normal leading-[20px] text-[#7D7D7D] - } - - div { - @apply flex flex-col gap-2 text-start - } + @apply text-blue flex gap-2 p-2 border border-blue hover:opacity-80 rounded-lg text-left w-fit; } .font-roberto { @@ -117,6 +105,10 @@ font-family: 'Oswald', sans-serif; } +.control-button { + @apply bg-white p-2 rounded-md pointer-events-auto; +} + ::-webkit-scrollbar { width: 20px; height: 20px; diff --git a/app/page.tsx b/app/page.tsx index 5f2317f3..9b35a945 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,21 +1,29 @@ 'use client' -import { useEffect, useRef, useState } from 'react'; +import { MutableRefObject, useEffect, useRef, useState } from 'react'; import { Chat } from './components/chat'; -import { Graph, GraphData } from './components/model'; -import { BookOpen, Github, HomeIcon, Search, X } from 'lucide-react'; +import { Graph, GraphData, Link as LinkType, Node} from './components/model'; +import { AlignRight, BookOpen, BoomBox, Download, Github, HomeIcon, Search, X } from 'lucide-react'; import Link from 'next/link'; -import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels"; +import { ImperativePanelHandle, Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels"; import { CodeGraph } from './components/code-graph'; import { toast } from '@/components/ui/use-toast'; -import { GraphContext } from './components/provider'; +import { VisuallyHidden } from '@radix-ui/react-visually-hidden'; import Image from 'next/image'; import { DropdownMenu, DropdownMenuContent, DropdownMenuLabel, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'; import { prepareArg } from './utils'; import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from '@/components/ui/carousel'; -import { Drawer, DrawerContent, DrawerTrigger } from '@/components/ui/drawer'; +import { Drawer, DrawerContent, DrawerDescription, DrawerTitle, DrawerTrigger } from '@/components/ui/drawer'; import Input from './components/Input'; -import { NodeObject } from 'react-force-graph-2d'; +import { ForceGraphMethods, NodeObject } from 'react-force-graph-2d'; +import { Labels } from './components/labels'; +import { Toolbar } from './components/toolbar'; +import { cn } from '@/lib/utils'; + +export type PathData = { + nodes: any[] + links: any[] +} export type PathNode = { id?: number @@ -33,6 +41,22 @@ type Tip = { keyboardCommand: string } +export enum MessageTypes { + Query, + Response, + Path, + PathResponse, + Pending, + Text, +} + +export interface Message { + type: MessageTypes; + text?: string; + paths?: { nodes: any[], links: any[] }[]; + graphName?: string; +} + const TIPS: Tip[] = [ { title: "Select Items in Specific Area", @@ -66,15 +90,26 @@ export default function Home() { const [options, setOptions] = useState([]); const [path, setPath] = useState(); const [isSubmit, setIsSubmit] = useState(false); - const chartRef = useRef() + const desktopChartRef = useRef>() + const mobileChartRef = useRef>() const [menuOpen, setMenuOpen] = useState(false) + const [chatOpen, setChatOpen] = useState(false) const [searchNode, setSearchNode] = useState({}); const [cooldownTicks, setCooldownTicks] = useState(0) const [cooldownTime, setCooldownTime] = useState(0) + const [optionsOpen, setOptionsOpen] = useState(false) + const [messages, setMessages] = useState([]); + const [query, setQuery] = useState(''); + const [selectedPath, setSelectedPath] = useState(); + const [paths, setPaths] = useState([]); + const chatPanel = useRef(null) useEffect(() => { - setIsPathResponse(false) - }, [graph.Id]) + if (path?.start?.id && path?.end?.id) { + console.log(path?.start?.id, path?.end?.id) + setChatOpen(true) + } + }, [path]) async function onCreateRepo(e: React.FormEvent) { e.preventDefault() @@ -137,6 +172,8 @@ export default function Home() { const json = await result.json() const g = Graph.create(json.result.entities, graphName) setGraph(g) + setIsPathResponse(false) + chatPanel.current?.expand() // @ts-ignore window.graph = g } @@ -166,7 +203,7 @@ export default function Home() { return graph.extend(json.result.neighbors, true) } - const handleSearchSubmit = (node: any) => { + const handleSearchSubmit = (node: any, chartRef: MutableRefObject | undefined>) => { const chart = chartRef.current if (chart) { @@ -189,11 +226,71 @@ export default function Home() { setTimeout(() => { chart.zoomToFit(1000, 150, (n: NodeObject) => n.id === chartNode!.id); }, 0) + setOptionsOpen(false) } } + function onCategoryClick(name: string, show: boolean) { + graph.Categories.find(c => c.name === name)!.show = show + + graph.Elements.nodes.forEach(node => { + if (!(node.category === name)) return + node.visible = show + }) + + graph.visibleLinks(show) + + setData({ ...graph.Elements }) + } + + const handleDownloadImage = async () => { + try { + const canvases = document.querySelectorAll('.force-graph-container canvas') as NodeListOf; + if (!canvases) { + toast({ + title: "Error", + description: "Canvas not found", + variant: "destructive", + }); + return; + } + + const canvas = Array.from(canvases).find(canvas => { + const container = canvas.parentElement; + + if (!container) return false; + + // Check if element is actually in viewport + const rect = container.getBoundingClientRect(); + const isInViewport = rect.width > 0 && + rect.height > 0 && + rect.top >= 0 && + rect.left >= 0 && + rect.bottom <= window.innerHeight && + rect.right <= window.innerWidth; + + return isInViewport; + }) + + if (!canvas) return; + + const dataURL = canvas.toDataURL('image/webp'); + const link = document.createElement('a'); + link.href = dataURL; + link.download = `${graph.Id}.webp`; + link.click(); + } catch (error) { + console.error('Error downloading graph image:', error); + toast({ + title: "Error", + description: "Failed to download image. Please try again.", + variant: "destructive", + }); + } + }; + return ( -
+
@@ -208,12 +305,16 @@ export default function Home() {
    -

    Home

    +

    Main Website

    Github

    + + +

    Discord

    +
- + handleSearchSubmit(node, desktopChartRef)} searchNode={searchNode} setSearchNode={setSearchNode} cooldownTicks={cooldownTicks} setCooldownTicks={setCooldownTicks} cooldownTime={cooldownTime} setCooldownTime={setCooldownTime} + onCategoryClick={onCategoryClick} + handleDownloadImage={handleDownloadImage} /> - - + +
-
+
- FalkorDB -
- { - menuOpen ? -
    + + {menuOpen && ( +
    +
    • Github

      @@ -361,10 +486,9 @@ export default function Home() {
    • @@ -379,57 +503,108 @@ export default function Home() {
    - : <> - - { - graph.Id && -
    +
    + )} +
    + handleSearchSubmit(node, mobileChartRef)} + setSearchNode={setSearchNode} + searchNode={searchNode} + cooldownTicks={cooldownTicks} + setCooldownTicks={setCooldownTicks} + cooldownTime={cooldownTime} + setCooldownTime={setCooldownTime} + onCategoryClick={onCategoryClick} + handleDownloadImage={handleDownloadImage} + /> + {graph.Id && ( +
    + + - - - - - - setSearchNode(node)} - icon={} - handleSubmit={handleSearchSubmit} - node={searchNode} - /> - - -
    - } - - } + + + + + + + + + + + + + + + + + + + + setSearchNode(node)} + icon={} + handleSubmit={(node) => handleSearchSubmit(node, mobileChartRef)} + node={searchNode} + /> + +
    + +

    Take Screenshot

    +
    +
    +
    +
    + )} +
) diff --git a/components/ui/drawer.tsx b/components/ui/drawer.tsx index 6a0ef53d..25a9aa9c 100644 --- a/components/ui/drawer.tsx +++ b/components/ui/drawer.tsx @@ -34,12 +34,17 @@ const DrawerOverlay = React.forwardRef< )) DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName +interface DrawerContentProps extends React.ComponentPropsWithoutRef { + overlayClassName?: string; + handleClassName?: string; +} + const DrawerContent = React.forwardRef< React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( + DrawerContentProps +>(({ className, overlayClassName, handleClassName, children, ...props }, ref) => ( - + -
+
{children} diff --git a/lib/utils.ts b/lib/utils.ts index faaa3e77..58da9d47 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -8,19 +8,31 @@ export function cn(...inputs: ClassValue[]) { export function handleZoomToFit(chartRef?: any) { const chart = chartRef.current if (chart) { - // Get canvas dimensions - const canvas = document.querySelector('.force-graph-container canvas.clickable') as HTMLCanvasElement; - if (!canvas) return; + // Find the currently visible canvas by checking display property + const canvases = document.querySelectorAll('.force-graph-container canvas') as NodeListOf; + const container = Array.from(canvases).find(canvas => { + const container = canvas.parentElement; + + if (!container) return false; - const container = canvas.parentElement; + // Check if element is actually in viewport + const rect = container.getBoundingClientRect(); + const isInViewport = rect.width > 0 && + rect.height > 0 && + rect.top >= 0 && + rect.left >= 0 && + rect.bottom <= window.innerHeight && + rect.right <= window.innerWidth; - if (!container) return; + return isInViewport; + })?.parentElement; - // Calculate padding as 1% of the smallest canvas dimension - const minDimension = Math.max(container.clientWidth, container.clientHeight); + if (!container) return; - const padding = minDimension * 0.1 + // Calculate padding as 10% of the smallest canvas dimension + const minDimension = Math.min(container.clientWidth, container.clientHeight); + const padding = minDimension * 0.1; - chart.zoomToFit(1000, padding) + chart.zoomToFit(1000, padding); } } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index d74f94fd..0b55ab33 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,11 +17,13 @@ "@radix-ui/react-slot": "^1.1.2", "@radix-ui/react-toast": "^1.2.2", "@radix-ui/react-tooltip": "^1.1.4", + "@radix-ui/react-visually-hidden": "^1.1.2", "@types/react-gtm-module": "^2.0.4", "autoprefixer": "^10.4.20", "canvas2svg": "^1.0.16", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "d3": "^7.9.0", "embla-carousel-react": "^8.5.2", "html2canvas": "^1.4.1", "lucide-react": "^0.441.0", @@ -2222,6 +2224,28 @@ } } }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-visually-hidden": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.1.tgz", + "integrity": "sha512-vVfA2IZ9q/J+gEamvj761Oq1FpWgCDaNOOIfbPVp2MVPLEomUr5+Vf7kJGwQ24YxZSlQVar7Bes8kyTo5Dshpg==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-slot": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", @@ -2383,6 +2407,28 @@ } } }, + "node_modules/@radix-ui/react-toast/node_modules/@radix-ui/react-visually-hidden": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.1.tgz", + "integrity": "sha512-vVfA2IZ9q/J+gEamvj761Oq1FpWgCDaNOOIfbPVp2MVPLEomUr5+Vf7kJGwQ24YxZSlQVar7Bes8kyTo5Dshpg==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-tooltip": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.5.tgz", @@ -2541,6 +2587,28 @@ } } }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-visually-hidden": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.1.tgz", + "integrity": "sha512-vVfA2IZ9q/J+gEamvj761Oq1FpWgCDaNOOIfbPVp2MVPLEomUr5+Vf7kJGwQ24YxZSlQVar7Bes8kyTo5Dshpg==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-use-callback-ref": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", @@ -2659,11 +2727,11 @@ } }, "node_modules/@radix-ui/react-visually-hidden": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.1.tgz", - "integrity": "sha512-vVfA2IZ9q/J+gEamvj761Oq1FpWgCDaNOOIfbPVp2MVPLEomUr5+Vf7kJGwQ24YxZSlQVar7Bes8kyTo5Dshpg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.2.tgz", + "integrity": "sha512-1SzA4ns2M1aRlvxErqhLHsBHoS5eI5UUcI2awAMgGUp4LoaoWOKYmvqDY2s/tltuPkh3Yk77YF/r3IRj+Amx4Q==", "dependencies": { - "@radix-ui/react-primitive": "2.0.1" + "@radix-ui/react-primitive": "2.0.2" }, "peerDependencies": { "@types/react": "*", @@ -2680,26 +2748,12 @@ } } }, - "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", - "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-primitive": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz", - "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz", + "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==", "dependencies": { - "@radix-ui/react-slot": "1.1.1" + "@radix-ui/react-slot": "1.1.2" }, "peerDependencies": { "@types/react": "*", @@ -2716,23 +2770,6 @@ } } }, - "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-slot": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz", - "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/@radix-ui/rect": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz", @@ -3816,6 +3853,46 @@ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "license": "MIT" }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/d3-array": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", @@ -3827,11 +3904,45 @@ "node": ">=12" } }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "engines": { + "node": ">=12" + } + }, "node_modules/d3-binarytree": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/d3-binarytree/-/d3-binarytree-1.0.2.tgz", "integrity": "sha512-cElUNH+sHu95L04m92pG73t2MEJXKu+GeKUN1TJkFsu93E5W8E9Sc3kHEGJKgenGvj19m6upSn2EunvMgMD2Yw==" }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/d3-color": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", @@ -3840,6 +3951,28 @@ "node": ">=12" } }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/d3-dispatch": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", @@ -3860,6 +3993,38 @@ "node": ">=12" } }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, "node_modules/d3-ease": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", @@ -3868,6 +4033,30 @@ "node": ">=12" } }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/d3-force-3d": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/d3-force-3d/-/d3-force-3d-3.0.5.tgz", @@ -3891,6 +4080,25 @@ "node": ">=12" } }, + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "engines": { + "node": ">=12" + } + }, "node_modules/d3-interpolate": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", @@ -3907,6 +4115,22 @@ "resolved": "https://registry.npmjs.org/d3-octree/-/d3-octree-1.0.2.tgz", "integrity": "sha512-Qxg4oirJrNXauiuC94uKMbgxwnhdda9xRLl9ihq45srlJ4Ga3CSgqGcAL8iW7N5CIv4Oz8x3E734ulxyvHPvwA==" }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "engines": { + "node": ">=12" + } + }, "node_modules/d3-quadtree": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", @@ -3915,6 +4139,14 @@ "node": ">=12" } }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "engines": { + "node": ">=12" + } + }, "node_modules/d3-scale": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", @@ -3950,6 +4182,17 @@ "node": ">=12" } }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/d3-time": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", @@ -4134,6 +4377,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delaunator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, "node_modules/detect-libc": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", @@ -5430,6 +5681,17 @@ "node": ">=8.0.0" } }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -7269,6 +7531,11 @@ "node": ">=0.10.0" } }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -7292,6 +7559,11 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, "node_modules/safe-array-concat": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", @@ -7328,6 +7600,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", diff --git a/package.json b/package.json index fc48ef94..9a481ed0 100644 --- a/package.json +++ b/package.json @@ -18,11 +18,13 @@ "@radix-ui/react-slot": "^1.1.2", "@radix-ui/react-toast": "^1.2.2", "@radix-ui/react-tooltip": "^1.1.4", + "@radix-ui/react-visually-hidden": "^1.1.2", "@types/react-gtm-module": "^2.0.4", "autoprefixer": "^10.4.20", "canvas2svg": "^1.0.16", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "d3": "^7.9.0", "embla-carousel-react": "^8.5.2", "html2canvas": "^1.4.1", "lucide-react": "^0.441.0", diff --git a/public/code-graph-logo.svg b/public/code-graph-logo.svg new file mode 100644 index 00000000..f06e5f18 --- /dev/null +++ b/public/code-graph-logo.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 11cb85136e8ef7f94216afb751f78e95bb3f46d5 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Thu, 20 Feb 2025 14:25:55 +0200 Subject: [PATCH 055/189] commit --- app/components/Input.tsx | 2 +- app/components/chat.tsx | 43 ++++++++++++++++------------------- app/components/code-graph.tsx | 7 +----- app/components/graphView.tsx | 27 ++++++++++++++++------ app/components/toolbar.tsx | 14 ++++++++---- docker-compose.yml | 23 ++++++++++--------- 6 files changed, 63 insertions(+), 53 deletions(-) diff --git a/app/components/Input.tsx b/app/components/Input.tsx index a2f29a9e..635469ea 100644 --- a/app/components/Input.tsx +++ b/app/components/Input.tsx @@ -169,7 +169,7 @@ export default function Input({ onValueChange, handleSubmit, graph, icon, node, open &&
- { - repo && -
- - - - - - {getTip("!w-full")} - - -
- - -
-
- } + + + {getTip("!w-full")} + + +
+ + +
+
); } diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 1c5b3b2c..150387e8 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -363,13 +363,8 @@ export function CodeGraph({ -
diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 2492e854..61bdabf8 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -65,6 +65,19 @@ export default function GraphView({ const lastClick = useRef<{ date: Date, name: string }>({ date: new Date(), name: "" }) const [parentWidth, setParentWidth] = useState(0) const [parentHeight, setParentHeight] = useState(0) + const [screenSize, setScreenSize] = useState(0) + + useEffect(() => { + const handleResize = () => { + setScreenSize(window.innerWidth) + } + + window.addEventListener('resize', handleResize) + + return () => { + window.removeEventListener('resize', handleResize) + } + }, []) useEffect(() => { const handleResize = () => { @@ -103,19 +116,19 @@ export default function GraphView({ setSelectedObjects([]) } - const handleRightClick = (node: Node | Link, evt: MouseEvent) => { - if (evt.ctrlKey && "category" in node) { - if (selectedObjects.some(obj => obj.id === node.id)) { - setSelectedObjects(selectedObjects.filter(obj => obj.id !== node.id)) + const handleRightClick = (element: Node | Link, evt: MouseEvent) => { + if (evt.ctrlKey && "category" in element) { + if (selectedObjects.some(obj => obj.id === element.id)) { + setSelectedObjects(selectedObjects.filter(obj => obj.id !== element.id)) return } else { - setSelectedObjects([...selectedObjects, node as Node]) + setSelectedObjects([...selectedObjects, element as Node]) } } else { setSelectedObjects([]) } - setSelectedObj(node) + setSelectedObj(element) setPosition({ x: evt.clientX, y: evt.clientY }) } @@ -272,7 +285,7 @@ export default function GraphView({ ctx.fillText(link.label, 0, 0); ctx.restore() }} - onNodeClick={handleNodeClick} + onNodeClick={screenSize > Number(process.env.NEXT_PUBLIC_MOBILE_BREAKPOINT) ? handleNodeClick : handleRightClick} onNodeDragEnd={(n, translate) => setPosition(prev => { return prev && { x: prev.x + translate.x * chartRef.current.zoom(), y: prev.y + translate.y * chartRef.current.zoom() } })} diff --git a/app/components/toolbar.tsx b/app/components/toolbar.tsx index ff5b7810..fe2bc74e 100644 --- a/app/components/toolbar.tsx +++ b/app/components/toolbar.tsx @@ -1,4 +1,4 @@ -import { CircleDot, Fullscreen, Minus, Plus, ZoomIn, ZoomOut } from "lucide-react"; +import { CircleDot, Download, Fullscreen, Minus, Plus, ZoomIn, ZoomOut } from "lucide-react"; import { cn } from "@/lib/utils" import { MutableRefObject } from "react"; import { ForceGraphMethods } from "react-force-graph-2d"; @@ -6,12 +6,12 @@ import { Link, Node } from "./model"; interface Props { chartRef: MutableRefObject | undefined> className?: string + handleDownloadImage?: () => void } -export function Toolbar({ chartRef, className }: Props) { +export function Toolbar({ chartRef, className, handleDownloadImage }: Props) { const handleZoomClick = (changefactor: number) => { - debugger const chart = chartRef.current if (chart) { chart.zoom(chart.zoom() * changefactor) @@ -19,10 +19,8 @@ export function Toolbar({ chartRef, className }: Props) { } const handleCenterClick = () => { - debugger const chart = chartRef.current if (chart) { - console.log(chart.getGraphBbox()) chart.zoomToFit(1000, 40) } } @@ -50,6 +48,12 @@ export function Toolbar({ chartRef, className }: Props) { > +
) } \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 2e4ac22b..8fe00e81 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,26 +11,27 @@ services: stdin_open: true # Keep the container's STDIN open tty: true # Allocate a pseudo-TTY - code-graph-frontend: - image: falkordb/code-graph-frontend:latest - ports: - - "3000:3000" - depends_on: - - code-graph-backend - environment: - - BACKEND_URL=http://code-graph-backend:5000 # Backend service URL - - SECRET_TOKEN=Vespa + # code-graph-frontend: + # image: falkordb/code-graph-frontend:latest + # ports: + # - "3000:3000" + # depends_on: + # - code-graph-backend + # environment: + # - BACKEND_URL=http://code-graph-backend:5000 # Backend service URL + # - SECRET_TOKEN=Vespa code-graph-backend: image: falkordb/code-graph-backend:latest ports: - - "4000:5000" + - "5000:5000" depends_on: - falkordb environment: - FALKORDB_HOST=falkordb - FALKORDB_PORT=6379 - OPENAI_API_KEY=YOUR_OPENAI_API_KEY - - SECRET_TOKEN=Vespa + - SECRET_TOKEN=sC0tTerMania - FLASK_RUN_HOST=0.0.0.0 - FLASK_RUN_PORT=5000 + - CODE_GRAPH_PUBLIC=1 \ No newline at end of file From 41b72f172959e84b1320f902d390a546ecb93120 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Sun, 23 Feb 2025 12:27:13 +0200 Subject: [PATCH 056/189] Improve link label rendering in graph view --- app/components/graphView.tsx | 71 +++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 1e67f2dd..78b4bd98 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -1,4 +1,3 @@ - import ForceGraph2D, { ForceGraphMethods } from 'react-force-graph-2d'; import { Graph, GraphData, Link, Node } from './model'; import { Dispatch, RefObject, SetStateAction, useEffect, useRef, useState } from 'react'; @@ -232,38 +231,66 @@ export default function GraphView({ if (!start.x || !start.y || !end.x || !end.y) return + let textX, textY, angle; + if (start.id === end.id) { const radius = NODE_SIZE * link.curve * 6.2; const angleOffset = -Math.PI / 4; // 45 degrees offset for text alignment - const textX = start.x + radius * Math.cos(angleOffset); - const textY = start.y + radius * Math.sin(angleOffset); - - ctx.save(); - ctx.translate(textX, textY); - ctx.rotate(-angleOffset); + textX = start.x + radius * Math.cos(angleOffset); + textY = start.y + radius * Math.sin(angleOffset); + angle = -angleOffset; } else { - const midX = (start.x + end.x) / 2 + (end.y - start.y) * (link.curve / 2); - const midY = (start.y + end.y) / 2 + (start.x - end.x) * (link.curve / 2); - - let textAngle = Math.atan2(end.y - start.y, end.x - start.x) - + const midX = (start.x + end.x) / 2; + const midY = (start.y + end.y) / 2; + const offset = link.curve / 2; + + angle = Math.atan2(end.y - start.y, end.x - start.x); + // maintain label vertical orientation for legibility - if (textAngle > Math.PI / 2) textAngle = -(Math.PI - textAngle); - if (textAngle < -Math.PI / 2) textAngle = -(-Math.PI - textAngle); - - ctx.save(); - ctx.translate(midX, midY); - ctx.rotate(textAngle); + if (angle > Math.PI / 2) angle = -(Math.PI - angle); + if (angle < -Math.PI / 2) angle = -(-Math.PI - angle); + + // Calculate perpendicular offset + const perpX = -Math.sin(angle) * offset; + const perpY = Math.cos(angle) * offset; + + // Adjust position to compensate for rotation around origin + const cos = Math.cos(angle); + const sin = Math.sin(angle); + textX = midX + perpX; + textY = midY + perpY; + const rotatedX = textX * cos + textY * sin; + const rotatedY = -textX * sin + textY * cos; + textX = rotatedX; + textY = rotatedY; } - // add label + // Setup text properties to measure background size + ctx.font = '2px Arial'; + const padding = 0.5; + const textWidth = ctx.measureText(link.label).width; + const textHeight = 2; // Approximate height for 2px font + + // add label with background and rotation + ctx.rotate(angle); + + // Draw background + ctx.fillStyle = 'white'; + ctx.fillRect( + textX - textWidth/2 - padding, + textY - textHeight/2 - padding, + textWidth + padding * 2, + textHeight + padding * 2 + ); + + // Draw text ctx.globalAlpha = 1; ctx.fillStyle = 'black'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; - ctx.font = '2px Arial'; - ctx.fillText(link.label, 0, 0); - ctx.restore() + ctx.fillText(link.label, textX, textY); + + ctx.rotate(-angle); // reset rotation }} onNodeClick={handleNodeClick} onNodeDragEnd={(n, translate) => setPosition(prev => { From 8ab51c625b0107756868bd506555b81246e0a93b Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Sun, 23 Feb 2025 14:29:22 +0200 Subject: [PATCH 057/189] commit --- app/components/code-graph.tsx | 18 ++++++++++-------- app/components/elementMenu.tsx | 30 ++++++++++++++++++++++++------ app/components/graphView.tsx | 6 +++--- 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 150387e8..8324ab53 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -95,7 +95,7 @@ export function CodeGraph({ const handleKeyDown = (event: KeyboardEvent) => { if (event.key === 'Delete') { if (selectedObj && selectedObjects.length === 0) return - handleRemove([...selectedObjects.map(obj => obj.id), selectedObj?.id].filter(id => id !== undefined)); + handleRemove([...selectedObjects.map(obj => obj.id), selectedObj?.id].filter(id => id !== undefined), "nodes"); } }; @@ -224,14 +224,17 @@ export function CodeGraph({ setData({ ...graph.Elements }) } - const handleRemove = (ids: number[]) => { - graph.Elements.nodes.forEach(node => { - if (!ids.includes(node.id)) return - node.visible = false + const handleRemove = (ids: number[], type: "nodes" | "links") => { + graph.Elements[type].forEach(element => { + if (!ids.includes(element.id)) return + element.visible = false }) graph.visibleLinks(false, ids) + setSelectedObj(undefined) + setSelectedObjects([]) + setData({ ...graph.Elements }) } @@ -280,15 +283,14 @@ export function CodeGraph({ } { - (graph.Elements.nodes.some(e => !e.visible)) && + (graph.getElements().some(e => !e.visible)) && @@ -87,7 +87,25 @@ export default function ElementMenu({ obj, objects, setPath, handleRemove, posit @@ -96,7 +114,7 @@ export default function ElementMenu({ obj, objects, setPath, handleRemove, posit diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 61bdabf8..16f2a098 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -4,7 +4,7 @@ import ForceGraph2D from 'react-force-graph-2d'; import { Graph, GraphData, Link, Node } from './model'; import { Dispatch, RefObject, SetStateAction, useEffect, useRef, useState } from 'react'; import { Path } from '../page'; -import { CircleDot, Fullscreen } from 'lucide-react'; +import { Fullscreen } from 'lucide-react'; import { handleZoomToFit } from '@/lib/utils'; export interface Position { @@ -286,12 +286,12 @@ export default function GraphView({ ctx.restore() }} onNodeClick={screenSize > Number(process.env.NEXT_PUBLIC_MOBILE_BREAKPOINT) ? handleNodeClick : handleRightClick} + onNodeRightClick={handleRightClick} onNodeDragEnd={(n, translate) => setPosition(prev => { return prev && { x: prev.x + translate.x * chartRef.current.zoom(), y: prev.y + translate.y * chartRef.current.zoom() } })} - onNodeRightClick={handleRightClick} + onLinkClick={screenSize > Number(process.env.NEXT_PUBLIC_MOBILE_BREAKPOINT) && isShowPath ? handleLinkClick : handleRightClick} onLinkRightClick={handleRightClick} - onLinkClick={handleLinkClick} onBackgroundRightClick={unsetSelectedObjects} onBackgroundClick={unsetSelectedObjects} onZoom={() => unsetSelectedObjects()} From dbd6c350cffd076d9d89e9b63e4d7034572b773f Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Sun, 23 Feb 2025 14:34:37 +0200 Subject: [PATCH 058/189] commit --- app/components/graphView.tsx | 29 ++++++++++++++++++++--------- app/components/model.ts | 31 +++++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 78b4bd98..9b9d1f0c 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -232,7 +232,7 @@ export default function GraphView({ if (!start.x || !start.y || !end.x || !end.y) return let textX, textY, angle; - + if (start.id === end.id) { const radius = NODE_SIZE * link.curve * 6.2; const angleOffset = -Math.PI / 4; // 45 degrees offset for text alignment @@ -243,9 +243,9 @@ export default function GraphView({ const midX = (start.x + end.x) / 2; const midY = (start.y + end.y) / 2; const offset = link.curve / 2; - + angle = Math.atan2(end.y - start.y, end.x - start.x); - + // maintain label vertical orientation for legibility if (angle > Math.PI / 2) angle = -(Math.PI - angle); if (angle < -Math.PI / 2) angle = -(-Math.PI - angle); @@ -265,20 +265,31 @@ export default function GraphView({ textY = rotatedY; } + // Get text width + const label = graph.LabelsMap.get(link.label)! + let { textWidth } = label + + if (!textWidth) { + textWidth = ctx.measureText(link.label).width; + graph.LabelsMap.set(link.label, { ...label, textWidth }) + } + // Setup text properties to measure background size ctx.font = '2px Arial'; const padding = 0.5; - const textWidth = ctx.measureText(link.label).width; const textHeight = 2; // Approximate height for 2px font + // Save the current context state + ctx.save(); + // add label with background and rotation ctx.rotate(angle); - + // Draw background ctx.fillStyle = 'white'; ctx.fillRect( - textX - textWidth/2 - padding, - textY - textHeight/2 - padding, + textX - textWidth / 2 - padding, + textY - textHeight / 2 - padding, textWidth + padding * 2, textHeight + padding * 2 ); @@ -289,8 +300,8 @@ export default function GraphView({ ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText(link.label, textX, textY); - - ctx.rotate(-angle); // reset rotation + + ctx.restore(); // reset rotation }} onNodeClick={handleNodeClick} onNodeDragEnd={(n, translate) => setPosition(prev => { diff --git a/app/components/model.ts b/app/components/model.ts index d38bc3a2..3df05a24 100644 --- a/app/components/model.ts +++ b/app/components/model.ts @@ -11,6 +11,11 @@ export interface Category { show: boolean, } +export interface Label { + name: string, + textWidth: number, +} + export type Node = NodeObject<{ id: number, name: string, @@ -62,18 +67,21 @@ export class Graph { private id: string; private categories: Category[]; + private labels: Label[]; private elements: GraphData; - private categoriesMap: Map; + private labelsMap: Map; private nodesMap: Map; private linksMap: Map; - private constructor(id: string, categories: Category[], elements: GraphData, - categoriesMap: Map, nodesMap: Map, edgesMap: Map) { + private constructor(id: string, categories: Category[], labels: Label[], elements: GraphData, + categoriesMap: Map, labelsMap: Map, nodesMap: Map, edgesMap: Map) { this.id = id; this.categories = categories; + this.labels = labels; this.elements = elements; this.categoriesMap = categoriesMap; + this.labelsMap = labelsMap; this.nodesMap = nodesMap; this.linksMap = edgesMap; } @@ -90,6 +98,14 @@ export class Graph { return this.categoriesMap; } + get Labels(): Label[] { + return this.labels; + } + + get LabelsMap(): Map { + return this.labelsMap; + } + get Elements(): GraphData { return this.elements; } @@ -111,7 +127,7 @@ export class Graph { } public static empty(): Graph { - return new Graph("", [], { nodes: [], links: [] }, new Map(), new Map(), new Map()) + return new Graph("", [], [], { nodes: [], links: [] }, new Map(), new Map(), new Map(), new Map()) } public static create(results: any, graphName: string): Graph { @@ -207,6 +223,13 @@ export class Graph { this.nodesMap.set(edgeData.dest_node, target) } + let label = this.labelsMap.get(edgeData.relation) + if (!label) { + label = { name: edgeData.relation, textWidth: 0 } + this.labelsMap.set(edgeData.relation, label) + this.labels.push(label) + } + link = { id: edgeData.id, source, From 1b985e59ed2b2299279dd1a9e2ee73538414b9b5 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Mon, 24 Feb 2025 13:11:53 +0200 Subject: [PATCH 059/189] commit --- app/components/chat.tsx | 10 +++++----- app/components/code-graph.tsx | 9 ++++----- app/components/graphView.tsx | 18 +++++++++--------- app/components/toolbar.tsx | 2 +- app/page.tsx | 4 ++-- lib/utils.ts | 5 +++++ 6 files changed, 26 insertions(+), 22 deletions(-) diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 65c1ad05..7eb082be 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -1,15 +1,15 @@ import { toast } from "@/components/ui/use-toast"; -import { Dispatch, FormEvent, SetStateAction, useEffect, useRef, useState } from "react"; +import { Dispatch, FormEvent, MutableRefObject, SetStateAction, useEffect, useRef, useState } from "react"; import Image from "next/image"; import { AlignLeft, ArrowRight, ChevronDown, Lightbulb, Undo2 } from "lucide-react"; import { Message, MessageTypes, Path, PathData } from "../page"; import Input from "./Input"; -import { Graph, GraphData } from "./model"; -import { cn } from "@/lib/utils"; +import { Graph, GraphData, Link, Node } from "./model"; +import { cn, GraphRef } from "@/lib/utils"; import { TypeAnimation } from "react-type-animation"; import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; import { prepareArg } from "../utils"; -import { NodeObject } from "react-force-graph-2d"; +import { ForceGraphMethods, NodeObject } from "react-force-graph-2d"; interface Props { repo: string @@ -20,7 +20,7 @@ interface Props { isPathResponse: boolean | undefined setIsPathResponse: (isPathResponse: boolean | undefined) => void setData: Dispatch> - chartRef: any + chartRef: GraphRef messages: Message[] setMessages: Dispatch> query: string diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 8324ab53..d94522e8 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -1,4 +1,4 @@ -import { Dispatch, RefObject, SetStateAction, useEffect, useRef, useState } from "react"; +import { Dispatch, MutableRefObject, SetStateAction, useEffect, useRef, useState } from "react"; import { Graph, GraphData, Node, Link } from "./model"; import { Toolbar } from "./toolbar"; import { Labels } from "./labels"; @@ -13,6 +13,8 @@ import { Checkbox } from '@/components/ui/checkbox'; import dynamic from 'next/dynamic'; import { Position } from "./graphView"; import { prepareArg } from '../utils'; +import { ForceGraphMethods } from "react-force-graph-2d"; +import { GraphRef } from "@/lib/utils"; const GraphView = dynamic(() => import('./graphView')); @@ -26,7 +28,7 @@ interface Props { setOptions: Dispatch> isShowPath: boolean setPath: Dispatch> - chartRef: RefObject + chartRef: GraphRef selectedValue: string selectedPathId: number | undefined setSelectedPathId: (selectedPathId: number) => void @@ -178,8 +180,6 @@ export function CodeGraph({ const isTarget = graph.Elements.links.some(link => link.target.id === node.id && nodes.some(n => n.id === link.source.id)); - debugger - if (!isTarget) return true const deleted = graph.NodesMap.delete(Number(node.id)) @@ -324,7 +324,6 @@ export function CodeGraph({ setSelectedObj={setSelectedObj} setSelectedObjects={setSelectedObjects} setPosition={setPosition} - onFetchNode={onFetchNode} handleExpand={handleExpand} isShowPath={isShowPath} setPath={setPath} diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 16f2a098..a9b917ed 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -1,11 +1,11 @@ 'use client' -import ForceGraph2D from 'react-force-graph-2d'; +import ForceGraph2D, { ForceGraphMethods } from 'react-force-graph-2d'; import { Graph, GraphData, Link, Node } from './model'; -import { Dispatch, RefObject, SetStateAction, useEffect, useRef, useState } from 'react'; +import { Dispatch, MutableRefObject, SetStateAction, useEffect, useRef, useState } from 'react'; import { Path } from '../page'; import { Fullscreen } from 'lucide-react'; -import { handleZoomToFit } from '@/lib/utils'; +import { GraphRef, handleZoomToFit } from '@/lib/utils'; export interface Position { x: number, @@ -16,13 +16,12 @@ interface Props { data: GraphData setData: Dispatch> graph: Graph - chartRef: RefObject + chartRef: GraphRef selectedObj: Node | Link | undefined setSelectedObj: Dispatch> selectedObjects: Node[] setSelectedObjects: Dispatch> setPosition: Dispatch> - onFetchNode: (nodeIds: number[]) => Promise handleExpand: (nodes: Node[], expand: boolean) => void isShowPath: boolean setPath: Dispatch> @@ -48,7 +47,6 @@ export default function GraphView({ selectedObjects, setSelectedObjects, setPosition, - onFetchNode, handleExpand, isShowPath, setPath, @@ -72,6 +70,8 @@ export default function GraphView({ setScreenSize(window.innerWidth) } + handleResize() + window.addEventListener('resize', handleResize) return () => { @@ -285,12 +285,12 @@ export default function GraphView({ ctx.fillText(link.label, 0, 0); ctx.restore() }} - onNodeClick={screenSize > Number(process.env.NEXT_PUBLIC_MOBILE_BREAKPOINT) ? handleNodeClick : handleRightClick} + onNodeClick={screenSize > Number(process.env.NEXT_PUBLIC_MOBILE_BREAKPOINT) || isShowPath ? handleNodeClick : handleRightClick} onNodeRightClick={handleRightClick} onNodeDragEnd={(n, translate) => setPosition(prev => { - return prev && { x: prev.x + translate.x * chartRef.current.zoom(), y: prev.y + translate.y * chartRef.current.zoom() } + return prev && { x: prev.x + translate.x * (chartRef.current?.zoom() ?? 1), y: prev.y + translate.y * (chartRef.current?.zoom() ?? 1) } })} - onLinkClick={screenSize > Number(process.env.NEXT_PUBLIC_MOBILE_BREAKPOINT) && isShowPath ? handleLinkClick : handleRightClick} + onLinkClick={screenSize > Number(process.env.NEXT_PUBLIC_MOBILE_BREAKPOINT) && isPathResponse ? handleLinkClick : handleRightClick} onLinkRightClick={handleRightClick} onBackgroundRightClick={unsetSelectedObjects} onBackgroundClick={unsetSelectedObjects} diff --git a/app/components/toolbar.tsx b/app/components/toolbar.tsx index fe2bc74e..e5013b8a 100644 --- a/app/components/toolbar.tsx +++ b/app/components/toolbar.tsx @@ -4,7 +4,7 @@ import { MutableRefObject } from "react"; import { ForceGraphMethods } from "react-force-graph-2d"; import { Link, Node } from "./model"; interface Props { - chartRef: MutableRefObject | undefined> + chartRef: GraphRef className?: string handleDownloadImage?: () => void } diff --git a/app/page.tsx b/app/page.tsx index 9b35a945..8fea830a 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -540,7 +540,7 @@ export default function Home() {

Chat

- + @@ -573,7 +573,7 @@ export default function Home() {

Options

- + diff --git a/lib/utils.ts b/lib/utils.ts index 58da9d47..12b953bb 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -1,5 +1,10 @@ +import { Link, Node } from "@/app/components/model" import { type ClassValue, clsx } from "clsx" +import { MutableRefObject } from "react" import { twMerge } from "tailwind-merge" +import { ForceGraphMethods } from "react-force-graph-2d" + +export type GraphRef = MutableRefObject | undefined> export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) From 84830b4121132e09c2bd3197b162b8a27fb6e73b Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Tue, 25 Feb 2025 12:52:42 +0200 Subject: [PATCH 060/189] commit --- app/components/code-graph.tsx | 4 +- app/components/dataPanel.tsx | 216 +++++++++++++++++----------------- app/components/toolbar.tsx | 7 +- app/globals.css | 2 +- app/page.tsx | 8 +- 5 files changed, 119 insertions(+), 118 deletions(-) diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index d94522e8..696985dd 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -239,9 +239,9 @@ export function CodeGraph({ } return ( -
+
-
+
!excludedProperties.includes(k)) return ( -
-
-

{label.toUpperCase()}

- -
-
- { - object.map(([key, value]) => ( -
-

{key}:

- { - key === "src" ? - - {value} - - : typeof value === "object" ? - !excludedProperties.includes(k)))} - theme={{ - base00: '#343434', // background - base01: '#000000', - base02: '#CE9178', - base03: '#CE9178', // open values - base04: '#CE9178', - base05: '#CE9178', - base06: '#CE9178', - base07: '#CE9178', - base08: '#CE9178', - base09: '#b5cea8', // numbers - base0A: '#CE9178', - base0B: '#CE9178', // close values - base0C: '#CE9178', - base0D: '#99E4E5', // * keys - base0E: '#ae81ff', - base0F: '#cc6633' - }} - valueRenderer={(valueAsString, value, keyPath) => { - if (keyPath === "src") { - return - {value as string} - + <> +
+
+
+

{label.toUpperCase()}

+ +
+
+ { + object.map(([key, value]) => ( +
+

{key}:

+ { + key === "src" ? + {value as string} }} - /> - : {value} - } -
- )) - } -
-
+ )) + } +
+ -
+ newTab.scroll({ + top: obj.src_start, + behavior: 'smooth' + }) + }} + > + + Go to repo + + + } + +
+ ) } \ No newline at end of file diff --git a/app/components/toolbar.tsx b/app/components/toolbar.tsx index e5013b8a..60c97077 100644 --- a/app/components/toolbar.tsx +++ b/app/components/toolbar.tsx @@ -1,8 +1,7 @@ -import { CircleDot, Download, Fullscreen, Minus, Plus, ZoomIn, ZoomOut } from "lucide-react"; +import { Download, Fullscreen, ZoomIn, ZoomOut } from "lucide-react"; import { cn } from "@/lib/utils" -import { MutableRefObject } from "react"; -import { ForceGraphMethods } from "react-force-graph-2d"; -import { Link, Node } from "./model"; +import { GraphRef } from "@/lib/utils"; + interface Props { chartRef: GraphRef className?: string diff --git a/app/globals.css b/app/globals.css index e1f3eb46..a177bc2c 100644 --- a/app/globals.css +++ b/app/globals.css @@ -106,7 +106,7 @@ } .control-button { - @apply bg-white p-2 rounded-md pointer-events-auto; + @apply bg-white p-2 rounded-md pointer-events-auto shadow-lg; } ::-webkit-scrollbar { diff --git a/app/page.tsx b/app/page.tsx index 8fea830a..3a18ed2f 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -458,11 +458,11 @@ export default function Home() {
-
+
FalkorDB -
@@ -579,7 +579,7 @@ export default function Home() { -

Take Screenshot

+

Take Screenshot

From 63d4c755ecbaaefbc03d4b9a1e67798b38958285 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Tue, 25 Feb 2025 13:00:54 +0200 Subject: [PATCH 061/189] fix build --- app/components/Input.tsx | 2 +- app/components/chat.tsx | 2 +- app/components/code-graph.tsx | 7 +++---- app/components/elementMenu.tsx | 2 +- app/components/graphView.tsx | 6 +++--- app/components/model.ts | 2 +- app/page.tsx | 33 +-------------------------------- lib/utils.ts | 31 +++++++++++++++++++++++++++++++ 8 files changed, 42 insertions(+), 43 deletions(-) diff --git a/app/components/Input.tsx b/app/components/Input.tsx index 3ce6593b..58847655 100644 --- a/app/components/Input.tsx +++ b/app/components/Input.tsx @@ -1,7 +1,7 @@ import { toast } from "@/components/ui/use-toast" import { getCategoryColorName, getCategoryColorValue, Graph } from "./model" import { useEffect, useRef, useState } from "react" -import { PathNode } from "../page" +import { PathNode } from "@/lib/utils" import { cn } from "@/lib/utils" import { prepareArg } from "../utils" diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 7eb082be..3b2ba447 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -2,7 +2,7 @@ import { toast } from "@/components/ui/use-toast"; import { Dispatch, FormEvent, MutableRefObject, SetStateAction, useEffect, useRef, useState } from "react"; import Image from "next/image"; import { AlignLeft, ArrowRight, ChevronDown, Lightbulb, Undo2 } from "lucide-react"; -import { Message, MessageTypes, Path, PathData } from "../page"; +import { Message, MessageTypes, Path, PathData } from "@/lib/utils"; import Input from "./Input"; import { Graph, GraphData, Link, Node } from "./model"; import { cn, GraphRef } from "@/lib/utils"; diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 696985dd..1845ad7e 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -1,19 +1,18 @@ -import { Dispatch, MutableRefObject, SetStateAction, useEffect, useRef, useState } from "react"; +import { Dispatch, SetStateAction, useEffect, useRef, useState } from "react"; import { Graph, GraphData, Node, Link } from "./model"; import { Toolbar } from "./toolbar"; import { Labels } from "./labels"; -import { Download, GitFork, Search, X } from "lucide-react"; +import { GitFork, Search, X } from "lucide-react"; import ElementMenu from "./elementMenu"; import Combobox from "./combobox"; import { toast } from '@/components/ui/use-toast'; -import { Path, PathNode } from '../page'; +import { Path } from "@/lib/utils"; import Input from './Input'; // import CommitList from './commitList'; import { Checkbox } from '@/components/ui/checkbox'; import dynamic from 'next/dynamic'; import { Position } from "./graphView"; import { prepareArg } from '../utils'; -import { ForceGraphMethods } from "react-force-graph-2d"; import { GraphRef } from "@/lib/utils"; const GraphView = dynamic(() => import('./graphView')); diff --git a/app/components/elementMenu.tsx b/app/components/elementMenu.tsx index 495953e0..30159014 100644 --- a/app/components/elementMenu.tsx +++ b/app/components/elementMenu.tsx @@ -4,7 +4,7 @@ import { Dispatch, RefObject, SetStateAction, useEffect, useState } from "react" import { Link, Node } from "./model"; import { ChevronsLeftRight, Copy, EyeOff, Globe, Maximize2, Minimize2, Waypoints } from "lucide-react"; import DataPanel from "./dataPanel"; -import { Path } from "../page"; +import { Path } from "@/lib/utils"; import { Position } from "./graphView"; interface Props { diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index a9b917ed..35fe760e 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -1,9 +1,9 @@ 'use client' -import ForceGraph2D, { ForceGraphMethods } from 'react-force-graph-2d'; +import ForceGraph2D from 'react-force-graph-2d'; import { Graph, GraphData, Link, Node } from './model'; -import { Dispatch, MutableRefObject, SetStateAction, useEffect, useRef, useState } from 'react'; -import { Path } from '../page'; +import { Dispatch, SetStateAction, useEffect, useRef, useState } from 'react'; +import { Path } from '@/lib/utils'; import { Fullscreen } from 'lucide-react'; import { GraphRef, handleZoomToFit } from '@/lib/utils'; diff --git a/app/components/model.ts b/app/components/model.ts index d38bc3a2..9d62f693 100644 --- a/app/components/model.ts +++ b/app/components/model.ts @@ -1,5 +1,5 @@ import { LinkObject, NodeObject } from 'react-force-graph-2d' -import { Path } from '../page' +import { Path } from '@/lib/utils' export interface GraphData { nodes: Node[], diff --git a/app/page.tsx b/app/page.tsx index 3a18ed2f..5611a5d4 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -18,22 +18,7 @@ import Input from './components/Input'; import { ForceGraphMethods, NodeObject } from 'react-force-graph-2d'; import { Labels } from './components/labels'; import { Toolbar } from './components/toolbar'; -import { cn } from '@/lib/utils'; - -export type PathData = { - nodes: any[] - links: any[] -} - -export type PathNode = { - id?: number - name?: string -} - -export type Path = { - start?: PathNode, - end?: PathNode -} +import { cn, Message, Path, PathData, PathNode } from '@/lib/utils'; type Tip = { title: string @@ -41,22 +26,6 @@ type Tip = { keyboardCommand: string } -export enum MessageTypes { - Query, - Response, - Path, - PathResponse, - Pending, - Text, -} - -export interface Message { - type: MessageTypes; - text?: string; - paths?: { nodes: any[], links: any[] }[]; - graphName?: string; -} - const TIPS: Tip[] = [ { title: "Select Items in Specific Area", diff --git a/lib/utils.ts b/lib/utils.ts index 12b953bb..eff20679 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -4,6 +4,37 @@ import { MutableRefObject } from "react" import { twMerge } from "tailwind-merge" import { ForceGraphMethods } from "react-force-graph-2d" +export type PathData = { + nodes: any[] + links: any[] +} + +export type PathNode = { + id?: number + name?: string +} + +export type Path = { + start?: PathNode, + end?: PathNode +} + +export enum MessageTypes { + Query, + Response, + Path, + PathResponse, + Pending, + Text, +} + +export interface Message { + type: MessageTypes; + text?: string; + paths?: { nodes: any[], links: any[] }[]; + graphName?: string; +} + export type GraphRef = MutableRefObject | undefined> export function cn(...inputs: ClassValue[]) { From 32baa347b6efedd49ff1efbd85da8615b27888b7 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Tue, 25 Feb 2025 13:16:11 +0200 Subject: [PATCH 062/189] improve control buttons style --- app/components/toolbar.tsx | 2 +- app/globals.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/toolbar.tsx b/app/components/toolbar.tsx index 60c97077..35fd7b46 100644 --- a/app/components/toolbar.tsx +++ b/app/components/toolbar.tsx @@ -25,7 +25,7 @@ export function Toolbar({ chartRef, className, handleDownloadImage }: Props) { } return ( -
+
{ - TIPS.map((tip, index) => ( + DESKTOP_TIPS.map((tip, index) => (

{tip.title}

@@ -464,9 +469,6 @@ export default function Home() {

Item 1

- -

Item 2

-
From 76026b16a6c873827d873bec101ce8cf79b0d0f3 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Thu, 27 Feb 2025 13:05:17 +0200 Subject: [PATCH 065/189] fix tips --- app/page.tsx | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/app/page.tsx b/app/page.tsx index b0e5d9c6..5a3426d9 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -2,7 +2,7 @@ import { MutableRefObject, useEffect, useRef, useState } from 'react'; import { Chat } from './components/chat'; -import { Graph, GraphData, Link as LinkType, Node} from './components/model'; +import { Graph, GraphData, Link as LinkType, Node } from './components/model'; import { AlignRight, BookOpen, BoomBox, Download, Github, HomeIcon, Search, X } from 'lucide-react'; import Link from 'next/link'; import { ImperativePanelHandle, Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels"; @@ -12,7 +12,7 @@ import { VisuallyHidden } from '@radix-ui/react-visually-hidden'; import Image from 'next/image'; import { DropdownMenu, DropdownMenuContent, DropdownMenuLabel, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'; import { prepareArg } from './utils'; -import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from '@/components/ui/carousel'; +import { Carousel, CarouselApi, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from '@/components/ui/carousel'; import { Drawer, DrawerContent, DrawerDescription, DrawerTitle, DrawerTrigger } from '@/components/ui/drawer'; import Input from './components/Input'; import { ForceGraphMethods, NodeObject } from 'react-force-graph-2d'; @@ -77,6 +77,8 @@ export default function Home() { const [selectedPath, setSelectedPath] = useState(); const [paths, setPaths] = useState([]); const chatPanel = useRef(null) + const [activeIndex, setActiveIndex] = useState(0) + const [carouselApi, setCarouselApi] = useState() useEffect(() => { if (path?.start?.id && path?.end?.id) { @@ -85,6 +87,14 @@ export default function Home() { } }, [path]) + useEffect(() => { + if (!carouselApi) return + + carouselApi.on('select', () => { + setActiveIndex(carouselApi.selectedScrollSnap()) + }) + }, [carouselApi]) + async function onCreateRepo(e: React.FormEvent) { e.preventDefault() @@ -442,7 +452,7 @@ export default function Home() {
{menuOpen && ( -
+
  • @@ -460,18 +470,32 @@ export default function Home() {
  • - - -

    Item 1

    -
    + + {MOBILE_TIPS.map((tip, index) => ( + +

    {tip}

    +
    + ))}
    - - +
    + {MOBILE_TIPS.map((_, index) => ( +
    + ))} +
    + +
From cfd404f308710f8db2995bcbbadb0cace40b4b4d Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Thu, 27 Feb 2025 14:09:05 +0200 Subject: [PATCH 066/189] increase chat height --- app/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/page.tsx b/app/page.tsx index 5a3426d9..6317bc5b 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -535,7 +535,7 @@ export default function Home() {

Chat

- + From 5e66aeab3e9955b71248548764185b1e1c8b7dd5 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Sun, 2 Mar 2025 11:57:34 +0200 Subject: [PATCH 067/189] update overlap --- app/components/graphView.tsx | 40 +++++++++++++++--------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index fe4eb5f8..74764d88 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -139,31 +139,25 @@ export default function GraphView({ } } - const avoidOverlap = (nodes: Array<{ x?: number; y?: number }>) => { + const avoidOverlap = (nodes: Position[]) => { const spacing = NODE_SIZE * 2.5; - const validNodes = nodes.filter(node => node.x !== undefined && node.y !== undefined) as Array<{ x: number; y: number }>; + nodes.forEach((nodeA, i) => { + nodes.forEach((nodeB, j) => { + if (i !== j) { + const dx = nodeA.x - nodeB.x; + const dy = nodeA.y - nodeB.y; + const distance = Math.sqrt(dx * dx + dy * dy) || 1; - for (let i = 0; i < validNodes.length; i++) { - for (let j = i + 1; j < validNodes.length; j++) { - const nodeA = validNodes[i]; - const nodeB = validNodes[j]; - - const dx = nodeA.x - nodeB.x; - const dy = nodeA.y - nodeB.y; - const distance = Math.sqrt(dx * dx + dy * dy) || 1; - - if (distance < spacing) { - const pushStrength = (spacing - distance) / distance * 0.5; - const moveX = dx * pushStrength; - const moveY = dy * pushStrength; - - nodeA.x += moveX; - nodeA.y += moveY; - nodeB.x -= moveX; - nodeB.y -= moveY; + if (distance < spacing) { + const pushStrength = (spacing - distance) / distance * 0.5; + nodeA.x += dx * pushStrength; + nodeA.y += dy * pushStrength; + nodeB.x -= dx * pushStrength; + nodeB.y -= dy * pushStrength; + } } - } - } + }); + }); }; return ( @@ -173,7 +167,7 @@ export default function GraphView({ height={parentHeight} width={parentWidth} graphData={data} - onEngineTick={() => avoidOverlap(data.nodes)} + onEngineTick={() => avoidOverlap(data.nodes as Position[])} nodeVisibility="visible" linkVisibility="visible" linkCurvature="curve" From 035c09ecc2847722d7e51b44fdb8fdec833983bb Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Mon, 3 Mar 2025 14:15:23 +0200 Subject: [PATCH 068/189] fix tests --- app/components/code-graph.tsx | 1 + e2e/config/constants.ts | 1 + e2e/config/testData.ts | 2 +- e2e/logic/POM/codeGraph.ts | 23 +++++- e2e/logic/utils.ts | 7 +- e2e/tests/nodeDetailsPanel.spec.ts | 112 +++++++++++++++++------------ 6 files changed, 98 insertions(+), 48 deletions(-) diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 52e38983..3a74106f 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -380,6 +380,7 @@ export function CodeGraph({ />
:
diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 74764d88..df196948 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -1,8 +1,9 @@ -import ForceGraph2D, { ForceGraphMethods } from 'react-force-graph-2d'; +import ForceGraph2D, { ForceGraphMethods, NodeObject } from 'react-force-graph-2d'; import { Graph, GraphData, Link, Node } from './model'; import { Dispatch, RefObject, SetStateAction, useEffect, useRef, useState } from 'react'; import { Path } from '../page'; +import { handleZoomToFit } from '@/lib/utils'; export interface Position { x: number, @@ -30,6 +31,8 @@ interface Props { setCooldownTicks: Dispatch> cooldownTime: number | undefined setCooldownTime: Dispatch> + setZoomedNodes: Dispatch> + zoomedNodes: Node[] } const PATH_COLOR = "#ffde21" @@ -56,7 +59,9 @@ export default function GraphView({ cooldownTicks, cooldownTime, setCooldownTicks, - setCooldownTime + setCooldownTime, + zoomedNodes, + setZoomedNodes }: Props) { const parentRef = useRef(null) @@ -295,6 +300,8 @@ export default function GraphView({ onEngineStop={() => { setCooldownTicks(0) setCooldownTime(0) + handleZoomToFit(chartRef, zoomedNodes.length === 1 ? 4 : 1, (n: NodeObject) => zoomedNodes.some(node => node.id === n.id)) + setZoomedNodes([]) }} cooldownTicks={cooldownTicks} cooldownTime={cooldownTime} diff --git a/lib/utils.ts b/lib/utils.ts index d084ccad..139392eb 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -1,6 +1,74 @@ import { type ClassValue, clsx } from "clsx" import { twMerge } from "tailwind-merge" +import { ForceGraphMethods, NodeObject } from "react-force-graph-2d" +import { Link, Node } from "@/app/components/model" +import { MutableRefObject } from "react" + +export type PathData = { + nodes: any[] + links: any[] +} + +export type PathNode = { + id?: number + name?: string +} + +export type Path = { + start?: PathNode, + end?: PathNode +} + +export enum MessageTypes { + Query, + Response, + Path, + PathResponse, + Pending, + Text, +} + +export interface Message { + type: MessageTypes; + text?: string; + paths?: { nodes: any[], links: any[] }[]; + graphName?: string; +} + +export type GraphRef = MutableRefObject | undefined> export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } + +export function handleZoomToFit(chartRef: GraphRef, paddingMultiplier = 1, filter?: (node: NodeObject) => boolean) { + const chart = chartRef.current + if (chart) { + // Find the currently visible canvas by checking display property + const canvases = document.querySelectorAll('.force-graph-container canvas') as NodeListOf; + const container = Array.from(canvases).find(canvas => { + const container = canvas.parentElement; + + if (!container) return false; + + // Check if element is actually in viewport + const rect = container.getBoundingClientRect(); + const isInViewport = rect.width > 0 && + rect.height > 0 && + rect.top >= 0 && + rect.left >= 0 && + rect.bottom <= window.innerHeight && + rect.right <= window.innerWidth; + + return isInViewport; + })?.parentElement; + + if (!container) return; + + // Calculate padding as 10% of the smallest canvas dimension + const minDimension = Math.min(container.clientWidth, container.clientHeight); + const padding = minDimension * 0.1 * paddingMultiplier; + + chart.zoomToFit(1000, padding, filter); + } +} From 5c336c198a4842724d098766db3c1fe303eb6d08 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Tue, 4 Mar 2025 19:59:20 +0200 Subject: [PATCH 080/189] add logging --- e2e/logic/POM/codeGraph.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 1f0336df..3e047420 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -468,12 +468,15 @@ export default class CodeGraph extends BasePage { async nodeClick(x: number, y: number): Promise { for (let attempt = 1; attempt <= 3; attempt++) { - console.log("x: ", x, " y: ", y); await this.canvasElement.hover({ position: { x, y } }); - await this.page.waitForTimeout(500); + console.log("hover completed"); + + await this.page.waitForTimeout(1000); if (await waitForElementToBeVisible(this.nodeToolTip)) { + console.log("tooltip visible: ",this.nodeToolTip.isVisible()); + console.log("x: ", x, " y: ", y); await this.canvasElement.click({ position: { x, y }, button: 'right' }); return; } From 0f096b3126062cce3015b4784f2aa902f3aee5d9 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Tue, 4 Mar 2025 20:10:48 +0200 Subject: [PATCH 081/189] Update codeGraph.ts --- e2e/logic/POM/codeGraph.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 3e047420..65624a0f 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -474,12 +474,12 @@ export default class CodeGraph extends BasePage { await this.page.waitForTimeout(1000); - if (await waitForElementToBeVisible(this.nodeToolTip)) { + // if (await waitForElementToBeVisible(this.nodeToolTip)) { console.log("tooltip visible: ",this.nodeToolTip.isVisible()); console.log("x: ", x, " y: ", y); await this.canvasElement.click({ position: { x, y }, button: 'right' }); - return; - } + // return; + // } await this.page.waitForTimeout(1000); } From 505ffd199df9444270ad60b9d23d640e078c5fba Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Tue, 4 Mar 2025 20:15:46 +0200 Subject: [PATCH 082/189] Update codeGraph.ts --- e2e/logic/POM/codeGraph.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 65624a0f..46284be4 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -475,7 +475,8 @@ export default class CodeGraph extends BasePage { await this.page.waitForTimeout(1000); // if (await waitForElementToBeVisible(this.nodeToolTip)) { - console.log("tooltip visible: ",this.nodeToolTip.isVisible()); + const tooltip = await this.nodeToolTip.isVisible(); + console.log("tooltip visible: ",tooltip); console.log("x: ", x, " y: ", y); await this.canvasElement.click({ position: { x, y }, button: 'right' }); // return; From dc7b34014467617187c0a256ce7eeaf0ce9c9240 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Tue, 4 Mar 2025 20:47:46 +0200 Subject: [PATCH 083/189] fix tests --- e2e/logic/POM/codeGraph.ts | 4 ++-- e2e/logic/utils.ts | 24 ++++++++++-------------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 46284be4..32c8fdc9 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -479,12 +479,12 @@ export default class CodeGraph extends BasePage { console.log("tooltip visible: ",tooltip); console.log("x: ", x, " y: ", y); await this.canvasElement.click({ position: { x, y }, button: 'right' }); - // return; + // return; // } await this.page.waitForTimeout(1000); } - throw new Error("Tooltip not visible after multiple attempts!"); + // throw new Error("Tooltip not visible after multiple attempts!"); } async selectCodeGraphCheckbox(checkbox: string): Promise { diff --git a/e2e/logic/utils.ts b/e2e/logic/utils.ts index fbc6f92e..c1e270af 100644 --- a/e2e/logic/utils.ts +++ b/e2e/logic/utils.ts @@ -34,21 +34,17 @@ export const waitForStableText = async (locator: Locator, timeout: number = 5000 return stableText; }; -export const waitForElementToBeVisible = async (locator: Locator, time = 800, retry = 10 ): Promise => { - while (retry > 0) { - try { - await locator.waitFor({ state: 'visible', timeout: time }); - return true; - } catch (e) { - console.warn(`Retry ${retry}: Element not visible yet.`); - } - - retry--; - await delay(time); +export const waitForElementToBeVisible = async (locator:Locator,time=500,retry=5):Promise => { + + while(retry > 0){ + if(await locator.isVisible()){ + return true + } + retry = retry-1 + await delay(time) } - return false; -}; - + return false +} export function findNodeByName(nodes: { name: string }[], nodeName: string): any { return nodes.find((node) => node.name === nodeName); From 21a7bd59a1645e83466eb4f75066165399a0a667 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Tue, 4 Mar 2025 21:09:20 +0200 Subject: [PATCH 084/189] update nodeClick --- e2e/logic/POM/codeGraph.ts | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 32c8fdc9..b50c116a 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -468,25 +468,19 @@ export default class CodeGraph extends BasePage { async nodeClick(x: number, y: number): Promise { for (let attempt = 1; attempt <= 3; attempt++) { - await this.canvasElement.hover({ position: { x, y } }); - console.log("hover completed"); - - await this.page.waitForTimeout(1000); - - // if (await waitForElementToBeVisible(this.nodeToolTip)) { - const tooltip = await this.nodeToolTip.isVisible(); - console.log("tooltip visible: ",tooltip); - console.log("x: ", x, " y: ", y); - await this.canvasElement.click({ position: { x, y }, button: 'right' }); - // return; - // } + await this.page.waitForTimeout(500); + await this.canvasElement.click({ position: { x, y }, button: 'right' }); + if (await this.elementMenu.isVisible()) { + return; + } await this.page.waitForTimeout(1000); } - - // throw new Error("Tooltip not visible after multiple attempts!"); + + throw new Error(`Failed to click, elementMenu not visible after multiple attempts.`); } + async selectCodeGraphCheckbox(checkbox: string): Promise { await this.codeGraphCheckbox(checkbox).click(); } From d75147fd2ecd83db6749055f1e1366062a8e146c Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Tue, 4 Mar 2025 21:26:32 +0200 Subject: [PATCH 085/189] add test (#402) --- e2e/logic/POM/codeGraph.ts | 7 +++++++ e2e/tests/canvas.spec.ts | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index b50c116a..a3c53768 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -658,4 +658,11 @@ export default class CodeGraph extends BasePage { const centerY = boundingBox.y + boundingBox.height / 2; await this.page.mouse.click(centerX, centerY, { button: 'right' }); } + + async validateToolTipVisibility(x: number, y: number): Promise{ + await this.canvasElement.hover({ position: { x, y } }); + const isToolTipVisible = await waitForElementToBeVisible(this.nodeToolTip); + if (!isToolTipVisible) throw new Error("'View Node' button is not visible!"); + return isToolTipVisible + } } diff --git a/e2e/tests/canvas.spec.ts b/e2e/tests/canvas.spec.ts index db80e3ca..1d91a3fc 100644 --- a/e2e/tests/canvas.spec.ts +++ b/e2e/tests/canvas.spec.ts @@ -206,5 +206,16 @@ test.describe("Canvas tests", () => { const downloadPath = await download.path(); expect(fs.existsSync(downloadPath)).toBe(true); }) + + nodes.forEach((node) => { + test(`Verify tooltip appears when hovering over node: ${node.nodeName}`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + const initialGraph = await codeGraph.getGraphDetails(); + const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); + const targetNode = findNodeByName(convertCoordinates, node.nodeName); + expect(await codeGraph.validateToolTipVisibility(targetNode.screenX, targetNode.screenY)) + }) + }) }); From bc8d9986f5706b0afecedabbf492bd64813c9a53 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Tue, 4 Mar 2025 21:50:17 +0200 Subject: [PATCH 086/189] fix #402 --- e2e/logic/POM/codeGraph.ts | 7 +++---- e2e/tests/canvas.spec.ts | 4 +++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index a3c53768..e5440fd1 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -659,10 +659,9 @@ export default class CodeGraph extends BasePage { await this.page.mouse.click(centerX, centerY, { button: 'right' }); } - async validateToolTipVisibility(x: number, y: number): Promise{ + async isToolTipVisible(x: number, y: number): Promise{ await this.canvasElement.hover({ position: { x, y } }); - const isToolTipVisible = await waitForElementToBeVisible(this.nodeToolTip); - if (!isToolTipVisible) throw new Error("'View Node' button is not visible!"); - return isToolTipVisible + await this.page.waitForTimeout(500); + return await this.nodeToolTip.isVisible(); } } diff --git a/e2e/tests/canvas.spec.ts b/e2e/tests/canvas.spec.ts index 1d91a3fc..114740da 100644 --- a/e2e/tests/canvas.spec.ts +++ b/e2e/tests/canvas.spec.ts @@ -210,11 +210,13 @@ test.describe("Canvas tests", () => { nodes.forEach((node) => { test(`Verify tooltip appears when hovering over node: ${node.nodeName}`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await browser.setPageToFullScreen(); await codeGraph.selectGraph(GRAPH_ID); const initialGraph = await codeGraph.getGraphDetails(); const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); const targetNode = findNodeByName(convertCoordinates, node.nodeName); - expect(await codeGraph.validateToolTipVisibility(targetNode.screenX, targetNode.screenY)) + const isVisible = await codeGraph.isToolTipVisible(targetNode.screenX, targetNode.screenY); + expect(isVisible).toBe(true); }) }) From d83b5915e215bfa2069d27c79b432ebe628e2c89 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Tue, 4 Mar 2025 22:01:28 +0200 Subject: [PATCH 087/189] update tooltip visibility --- e2e/logic/POM/codeGraph.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index e5440fd1..e46c307c 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -659,9 +659,15 @@ export default class CodeGraph extends BasePage { await this.page.mouse.click(centerX, centerY, { button: 'right' }); } + async isNodeToolTipVisible(): Promise { + return await this.nodeToolTip.evaluate(el => + window.getComputedStyle(el).visibility === 'visible' + ); + } + async isToolTipVisible(x: number, y: number): Promise{ await this.canvasElement.hover({ position: { x, y } }); await this.page.waitForTimeout(500); - return await this.nodeToolTip.isVisible(); + return await this.isNodeToolTipVisible(); } } From e1c463f83cada3fb110cc90968cd8a48ad36f0c3 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Tue, 4 Mar 2025 22:18:48 +0200 Subject: [PATCH 088/189] update test --- e2e/logic/POM/codeGraph.ts | 14 ++++++++------ e2e/tests/canvas.spec.ts | 15 ++++++++------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index e46c307c..44b5dd33 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -659,15 +659,17 @@ export default class CodeGraph extends BasePage { await this.page.mouse.click(centerX, centerY, { button: 'right' }); } + async hoverAtCanvasCenter(): Promise { + const boundingBox = await this.canvasElement.boundingBox(); + if (!boundingBox) throw new Error('Canvas bounding box not found'); + const centerX = boundingBox.x + boundingBox.width / 2; + const centerY = boundingBox.y + boundingBox.height / 2; + await this.page.mouse.move(centerX, centerY); + } + async isNodeToolTipVisible(): Promise { return await this.nodeToolTip.evaluate(el => window.getComputedStyle(el).visibility === 'visible' ); - } - - async isToolTipVisible(x: number, y: number): Promise{ - await this.canvasElement.hover({ position: { x, y } }); - await this.page.waitForTimeout(500); - return await this.isNodeToolTipVisible(); } } diff --git a/e2e/tests/canvas.spec.ts b/e2e/tests/canvas.spec.ts index 114740da..979a255a 100644 --- a/e2e/tests/canvas.spec.ts +++ b/e2e/tests/canvas.spec.ts @@ -3,7 +3,7 @@ import BrowserWrapper from "../infra/ui/browserWrapper"; import CodeGraph from "../logic/POM/codeGraph"; import urls from "../config/urls.json"; import { GRAPH_ID, PROJECT_NAME } from "../config/constants"; -import { findNodeByName } from "../logic/utils"; +import { delay, findNodeByName } from "../logic/utils"; import { nodesPath, categories, nodes, graphs } from "../config/testData"; import { ApiCalls } from "../logic/api/apiCalls"; import fs from 'fs'; @@ -207,16 +207,17 @@ test.describe("Canvas tests", () => { expect(fs.existsSync(downloadPath)).toBe(true); }) - nodes.forEach((node) => { + nodes.slice(1,4).forEach((node) => { test(`Verify tooltip appears when hovering over node: ${node.nodeName}`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await browser.setPageToFullScreen(); await codeGraph.selectGraph(GRAPH_ID); - const initialGraph = await codeGraph.getGraphDetails(); - const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); - const targetNode = findNodeByName(convertCoordinates, node.nodeName); - const isVisible = await codeGraph.isToolTipVisible(targetNode.screenX, targetNode.screenY); - expect(isVisible).toBe(true); + await codeGraph.getGraphDetails(); + await codeGraph.fillSearchBar(node.nodeName); + await codeGraph.selectSearchBarOptionBtn("1"); + await delay(2000); + await codeGraph.hoverAtCanvasCenter(); + expect(await codeGraph.isNodeToolTipVisible()).toBe(true); }) }) From 08d899dc58f60c03814346412b4e5c8e3fcb596b Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Wed, 5 Mar 2025 10:03:29 +0200 Subject: [PATCH 089/189] update locators --- e2e/logic/POM/codeGraph.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 44b5dd33..59211346 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -668,8 +668,6 @@ export default class CodeGraph extends BasePage { } async isNodeToolTipVisible(): Promise { - return await this.nodeToolTip.evaluate(el => - window.getComputedStyle(el).visibility === 'visible' - ); + return await this.nodeToolTip.isVisible(); } } From 1b636398ed3b7a136bb12b97b26262ec851ba9fc Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Wed, 5 Mar 2025 10:27:56 +0200 Subject: [PATCH 090/189] update locators --- e2e/logic/POM/codeGraph.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 59211346..1cc5c8f5 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -668,6 +668,14 @@ export default class CodeGraph extends BasePage { } async isNodeToolTipVisible(): Promise { - return await this.nodeToolTip.isVisible(); + try { + await this.nodeToolTip.waitFor({ state: 'attached', timeout: 5000 }); + const box = await this.nodeToolTip.boundingBox(); + return box !== null; + } catch (error) { + console.error("Error checking tooltip visibility:", error); + return false; + } } + } From 6d2d286c69b6ff29d5ead4859637bd4dd5601df7 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Wed, 5 Mar 2025 10:35:21 +0200 Subject: [PATCH 091/189] Update codeGraph.ts --- e2e/logic/POM/codeGraph.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 1cc5c8f5..f6dc3d30 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -669,13 +669,13 @@ export default class CodeGraph extends BasePage { async isNodeToolTipVisible(): Promise { try { - await this.nodeToolTip.waitFor({ state: 'attached', timeout: 5000 }); - const box = await this.nodeToolTip.boundingBox(); - return box !== null; + await this.nodeToolTip.waitFor({ state: 'visible', timeout: 7000 }); + return await this.nodeToolTip.evaluate(el => getComputedStyle(el).visibility === 'visible'); } catch (error) { - console.error("Error checking tooltip visibility:", error); + console.error("Tooltip visibility check failed:", error); return false; } } + } From 2ac1435795a1aa292255949429de09d75278add5 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Wed, 5 Mar 2025 10:52:18 +0200 Subject: [PATCH 092/189] update test --- e2e/logic/POM/codeGraph.ts | 11 ++--------- e2e/tests/canvas.spec.ts | 2 +- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index f6dc3d30..c88f1e3b 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -667,15 +667,8 @@ export default class CodeGraph extends BasePage { await this.page.mouse.move(centerX, centerY); } - async isNodeToolTipVisible(): Promise { - try { - await this.nodeToolTip.waitFor({ state: 'visible', timeout: 7000 }); - return await this.nodeToolTip.evaluate(el => getComputedStyle(el).visibility === 'visible'); - } catch (error) { - console.error("Tooltip visibility check failed:", error); - return false; - } + async getTooltipVisibility(): Promise { + return await this.nodeToolTip.evaluate(el => getComputedStyle(el).visibility); } - } diff --git a/e2e/tests/canvas.spec.ts b/e2e/tests/canvas.spec.ts index 979a255a..af32c887 100644 --- a/e2e/tests/canvas.spec.ts +++ b/e2e/tests/canvas.spec.ts @@ -217,7 +217,7 @@ test.describe("Canvas tests", () => { await codeGraph.selectSearchBarOptionBtn("1"); await delay(2000); await codeGraph.hoverAtCanvasCenter(); - expect(await codeGraph.isNodeToolTipVisible()).toBe(true); + expect(await codeGraph.getTooltipVisibility()).toBe("visible"); }) }) From ddf1bc6a857a3cf6e9639212bbcab7a587df1b2f Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Wed, 5 Mar 2025 11:39:50 +0200 Subject: [PATCH 093/189] update test --- e2e/logic/POM/codeGraph.ts | 25 ++- e2e/tests/canvas.spec.ts | 368 ++++++++++++++++++------------------- 2 files changed, 207 insertions(+), 186 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index c88f1e3b..733e06c7 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -667,8 +667,29 @@ export default class CodeGraph extends BasePage { await this.page.mouse.move(centerX, centerY); } - async getTooltipVisibility(): Promise { - return await this.nodeToolTip.evaluate(el => getComputedStyle(el).visibility); + async isNodeToolTipVisible(): Promise { + try { + const count = await this.nodeToolTip.count(); + if (count === 0) { + console.error("Tooltip not found"); + return false; + } + + const box = await this.nodeToolTip.boundingBox(); + if (box && box.width > 0 && box.height > 0) { + return true; + } + + return await this.nodeToolTip.evaluate(el => { + const style = getComputedStyle(el); + return style.visibility === 'visible' && parseFloat(style.opacity) > 0; + }); + } catch (error) { + console.error("Tooltip visibility check failed:", error); + return false; + } } + + } diff --git a/e2e/tests/canvas.spec.ts b/e2e/tests/canvas.spec.ts index af32c887..3785b80c 100644 --- a/e2e/tests/canvas.spec.ts +++ b/e2e/tests/canvas.spec.ts @@ -19,193 +19,193 @@ test.describe("Canvas tests", () => { await browser.closeBrowser(); }); - test(`Verify zoom in functionality on canvas`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - const initialGraph = await codeGraph.getCanvasScaling(); - await codeGraph.clickZoomIn(); - await codeGraph.clickZoomIn(); - const updatedGraph = await codeGraph.getCanvasScaling(); - expect(updatedGraph.scaleX).toBeGreaterThan(initialGraph.scaleX) - expect(updatedGraph.scaleY).toBeGreaterThan(initialGraph.scaleY) - }) - - test(`Verify zoom out functionality on canvas`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - const initialGraph = await codeGraph.getCanvasScaling(); - await codeGraph.clickZoomOut(); - await codeGraph.clickZoomOut(); - const updatedGraph = await codeGraph.getCanvasScaling(); - expect(updatedGraph.scaleX).toBeLessThan(initialGraph.scaleX) - expect(updatedGraph.scaleY).toBeLessThan(initialGraph.scaleY) - }) - - test(`Verify center graph button centers nodes in canvas`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - await codeGraph.clickCenter(); - const initialGraph = await codeGraph.getCanvasScaling(); - await codeGraph.clickZoomOut(); - await codeGraph.clickZoomOut(); - await codeGraph.clickCenter(); - const updatedGraph = await codeGraph.getCanvasScaling(); - expect(Math.abs(initialGraph.scaleX - updatedGraph.scaleX)).toBeLessThanOrEqual(0.1); - expect(Math.abs(initialGraph.scaleY - updatedGraph.scaleY)).toBeLessThanOrEqual(0.1); - }) - - nodes.slice(0,2).forEach((node) => { - test(`Validate node hide functionality via element menu in canvas for ${node.nodeName}`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - const initialGraph = await codeGraph.getGraphDetails(); - const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); - const targetNode = findNodeByName(convertCoordinates, node.nodeName); - await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); - await codeGraph.clickOnRemoveNodeViaElementMenu(); - const updatedGraph = await codeGraph.getGraphDetails(); - const targetNodeForUpdateGraph = findNodeByName(updatedGraph.elements.nodes, node.nodeName); - expect(targetNodeForUpdateGraph.visible).toBe(false); - }); - }) - - nodes.slice(0,2).forEach((node) => { - test(`Validate unhide node functionality after hiding a node in canvas for ${node.nodeName}`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - const initialGraph = await codeGraph.getGraphDetails(); - const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); - const targetNode = findNodeByName(convertCoordinates, node.nodeName); - await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); - await codeGraph.clickOnRemoveNodeViaElementMenu(); - await codeGraph.clickOnUnhideNodesBtn(); - const updatedGraph = await codeGraph.getGraphDetails(); - const targetNodeForUpdateGraph = findNodeByName(updatedGraph.elements.nodes, node.nodeName); - expect(targetNodeForUpdateGraph.visible).toBe(true); - }); - }) - - categories.forEach((category, index) => { - const checkboxIndex = index + 1; - test(`Verify that unchecking the ${category} checkbox hides ${category} nodes on the canvas`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - await codeGraph.selectCodeGraphCheckbox(checkboxIndex.toString()); - const result = await codeGraph.getGraphDetails(); - const findItem = result.categories.find((item: { name: string; }) => item.name === category) - expect(findItem.show).toBe(false) - }); - }) - - nodesPath.forEach((path) => { - test(`Verify "Clear graph" button resets canvas view for path ${path.firstNode} and ${path.secondNode}`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - await codeGraph.clickOnShowPathBtn(); - await codeGraph.insertInputForShowPath("1", path.firstNode); - await codeGraph.insertInputForShowPath("2", path.secondNode); - const initialGraph = await codeGraph.getGraphDetails(); - const firstNode = findNodeByName(initialGraph.elements.nodes, path.firstNode); - const secondNode = findNodeByName(initialGraph.elements.nodes, path.secondNode); - expect(firstNode.isPath).toBe(true); - expect(secondNode.isPath).toBe(true); - await codeGraph.clickOnClearGraphBtn(); - const updateGraph = await codeGraph.getGraphDetails(); - const firstNode1 = findNodeByName(updateGraph.elements.nodes, path.firstNode); - const secondNode1 = findNodeByName(updateGraph.elements.nodes, path.secondNode); - expect(firstNode1.isPath).toBe(false); - expect(secondNode1.isPath).toBe(false); - }); - }) - - graphs.forEach(({graphName}) => { - test(`Verify selecting different graphs displays nodes in canvas - grpah: ${graphName}`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(graphName); - const result = await codeGraph.getGraphDetails(); - expect(result.elements.nodes.length).toBeGreaterThan(1); - expect(result.elements.links.length).toBeGreaterThan(1); - }); - }) + // test(`Verify zoom in functionality on canvas`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // const initialGraph = await codeGraph.getCanvasScaling(); + // await codeGraph.clickZoomIn(); + // await codeGraph.clickZoomIn(); + // const updatedGraph = await codeGraph.getCanvasScaling(); + // expect(updatedGraph.scaleX).toBeGreaterThan(initialGraph.scaleX) + // expect(updatedGraph.scaleY).toBeGreaterThan(initialGraph.scaleY) + // }) + + // test(`Verify zoom out functionality on canvas`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // const initialGraph = await codeGraph.getCanvasScaling(); + // await codeGraph.clickZoomOut(); + // await codeGraph.clickZoomOut(); + // const updatedGraph = await codeGraph.getCanvasScaling(); + // expect(updatedGraph.scaleX).toBeLessThan(initialGraph.scaleX) + // expect(updatedGraph.scaleY).toBeLessThan(initialGraph.scaleY) + // }) + + // test(`Verify center graph button centers nodes in canvas`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // await codeGraph.clickCenter(); + // const initialGraph = await codeGraph.getCanvasScaling(); + // await codeGraph.clickZoomOut(); + // await codeGraph.clickZoomOut(); + // await codeGraph.clickCenter(); + // const updatedGraph = await codeGraph.getCanvasScaling(); + // expect(Math.abs(initialGraph.scaleX - updatedGraph.scaleX)).toBeLessThanOrEqual(0.1); + // expect(Math.abs(initialGraph.scaleY - updatedGraph.scaleY)).toBeLessThanOrEqual(0.1); + // }) + + // nodes.slice(0,2).forEach((node) => { + // test(`Validate node hide functionality via element menu in canvas for ${node.nodeName}`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // const initialGraph = await codeGraph.getGraphDetails(); + // const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); + // const targetNode = findNodeByName(convertCoordinates, node.nodeName); + // await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); + // await codeGraph.clickOnRemoveNodeViaElementMenu(); + // const updatedGraph = await codeGraph.getGraphDetails(); + // const targetNodeForUpdateGraph = findNodeByName(updatedGraph.elements.nodes, node.nodeName); + // expect(targetNodeForUpdateGraph.visible).toBe(false); + // }); + // }) + + // nodes.slice(0,2).forEach((node) => { + // test(`Validate unhide node functionality after hiding a node in canvas for ${node.nodeName}`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // const initialGraph = await codeGraph.getGraphDetails(); + // const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); + // const targetNode = findNodeByName(convertCoordinates, node.nodeName); + // await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); + // await codeGraph.clickOnRemoveNodeViaElementMenu(); + // await codeGraph.clickOnUnhideNodesBtn(); + // const updatedGraph = await codeGraph.getGraphDetails(); + // const targetNodeForUpdateGraph = findNodeByName(updatedGraph.elements.nodes, node.nodeName); + // expect(targetNodeForUpdateGraph.visible).toBe(true); + // }); + // }) + + // categories.forEach((category, index) => { + // const checkboxIndex = index + 1; + // test(`Verify that unchecking the ${category} checkbox hides ${category} nodes on the canvas`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // await codeGraph.selectCodeGraphCheckbox(checkboxIndex.toString()); + // const result = await codeGraph.getGraphDetails(); + // const findItem = result.categories.find((item: { name: string; }) => item.name === category) + // expect(findItem.show).toBe(false) + // }); + // }) + + // nodesPath.forEach((path) => { + // test(`Verify "Clear graph" button resets canvas view for path ${path.firstNode} and ${path.secondNode}`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // await codeGraph.clickOnShowPathBtn(); + // await codeGraph.insertInputForShowPath("1", path.firstNode); + // await codeGraph.insertInputForShowPath("2", path.secondNode); + // const initialGraph = await codeGraph.getGraphDetails(); + // const firstNode = findNodeByName(initialGraph.elements.nodes, path.firstNode); + // const secondNode = findNodeByName(initialGraph.elements.nodes, path.secondNode); + // expect(firstNode.isPath).toBe(true); + // expect(secondNode.isPath).toBe(true); + // await codeGraph.clickOnClearGraphBtn(); + // const updateGraph = await codeGraph.getGraphDetails(); + // const firstNode1 = findNodeByName(updateGraph.elements.nodes, path.firstNode); + // const secondNode1 = findNodeByName(updateGraph.elements.nodes, path.secondNode); + // expect(firstNode1.isPath).toBe(false); + // expect(secondNode1.isPath).toBe(false); + // }); + // }) + + // graphs.forEach(({graphName}) => { + // test(`Verify selecting different graphs displays nodes in canvas - grpah: ${graphName}`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(graphName); + // const result = await codeGraph.getGraphDetails(); + // expect(result.elements.nodes.length).toBeGreaterThan(1); + // expect(result.elements.links.length).toBeGreaterThan(1); + // }); + // }) - for (let index = 0; index < 3; index++) { - const nodeIndex: number = index + 1; - test(`Validate canvas node dragging for node: ${index}`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - const initialGraph = await codeGraph.getGraphDetails(); - const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); - await codeGraph.changeNodePosition(convertCoordinates[nodeIndex].screenX, convertCoordinates[nodeIndex].screenY); - const updateGraph = await codeGraph.getGraphDetails(); - expect(updateGraph.elements.nodes[nodeIndex].x).not.toBe(initialGraph.elements.nodes[nodeIndex].x); - expect(updateGraph.elements.nodes[nodeIndex].y).not.toBe(initialGraph.elements.nodes[nodeIndex].y); - }); - } - - test(`Validate node and edge counts in canvas match API data`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - const { nodes, edges } = await codeGraph.getMetricsPanelInfo(); - const api = new ApiCalls(); - const response = await api.projectInfo(PROJECT_NAME); - expect(response.result.info.node_count).toEqual(parseInt(nodes)); - expect(response.result.info.edge_count).toEqual(parseInt(edges)); - }); + // for (let index = 0; index < 3; index++) { + // const nodeIndex: number = index + 1; + // test(`Validate canvas node dragging for node: ${index}`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // const initialGraph = await codeGraph.getGraphDetails(); + // const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); + // await codeGraph.changeNodePosition(convertCoordinates[nodeIndex].screenX, convertCoordinates[nodeIndex].screenY); + // const updateGraph = await codeGraph.getGraphDetails(); + // expect(updateGraph.elements.nodes[nodeIndex].x).not.toBe(initialGraph.elements.nodes[nodeIndex].x); + // expect(updateGraph.elements.nodes[nodeIndex].y).not.toBe(initialGraph.elements.nodes[nodeIndex].y); + // }); + // } + + // test(`Validate node and edge counts in canvas match API data`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // const { nodes, edges } = await codeGraph.getMetricsPanelInfo(); + // const api = new ApiCalls(); + // const response = await api.projectInfo(PROJECT_NAME); + // expect(response.result.info.node_count).toEqual(parseInt(nodes)); + // expect(response.result.info.edge_count).toEqual(parseInt(edges)); + // }); - test(`Validate displayed nodes match API response after selecting a graph via UI`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - const graphData = await codeGraph.getGraphDetails(); - const api = new ApiCalls(); - const response = await api.getProject(PROJECT_NAME); - const isMatching = graphData.elements.nodes.slice(0, 2).every( - (node: any, index: number) => node.name === response.result.entities.nodes[index].properties.name - ); - expect(isMatching).toBe(true) - }); - - nodesPath.forEach(({firstNode, secondNode}) => { - test(`Verify successful node path connection in canvas between ${firstNode} and ${secondNode} via UI`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - await codeGraph.clickOnShowPathBtn(); - await codeGraph.insertInputForShowPath("1", firstNode); - await codeGraph.insertInputForShowPath("2", secondNode); - const result = await codeGraph.getGraphDetails(); - const firstNodeRes = findNodeByName(result.elements.nodes, firstNode); - const secondnodeRes = findNodeByName(result.elements.nodes, secondNode); - expect(firstNodeRes.isPath).toBe(true) - expect(secondnodeRes.isPath).toBe(true) - }) - }) - - nodesPath.forEach((path) => { - test(`Validate node path connection in canvas ui and confirm via api for path ${path.firstNode} and ${path.secondNode}`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - await codeGraph.clickOnShowPathBtn(); - await codeGraph.insertInputForShowPath("1", path.firstNode); - await codeGraph.insertInputForShowPath("2", path.secondNode); - const result = await codeGraph.getGraphDetails(); - const firstNodeRes = findNodeByName(result.elements.nodes, path.firstNode); - const secondNodeRes = findNodeByName(result.elements.nodes, path.secondNode); + // test(`Validate displayed nodes match API response after selecting a graph via UI`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // const graphData = await codeGraph.getGraphDetails(); + // const api = new ApiCalls(); + // const response = await api.getProject(PROJECT_NAME); + // const isMatching = graphData.elements.nodes.slice(0, 2).every( + // (node: any, index: number) => node.name === response.result.entities.nodes[index].properties.name + // ); + // expect(isMatching).toBe(true) + // }); + + // nodesPath.forEach(({firstNode, secondNode}) => { + // test(`Verify successful node path connection in canvas between ${firstNode} and ${secondNode} via UI`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // await codeGraph.clickOnShowPathBtn(); + // await codeGraph.insertInputForShowPath("1", firstNode); + // await codeGraph.insertInputForShowPath("2", secondNode); + // const result = await codeGraph.getGraphDetails(); + // const firstNodeRes = findNodeByName(result.elements.nodes, firstNode); + // const secondnodeRes = findNodeByName(result.elements.nodes, secondNode); + // expect(firstNodeRes.isPath).toBe(true) + // expect(secondnodeRes.isPath).toBe(true) + // }) + // }) + + // nodesPath.forEach((path) => { + // test(`Validate node path connection in canvas ui and confirm via api for path ${path.firstNode} and ${path.secondNode}`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // await codeGraph.clickOnShowPathBtn(); + // await codeGraph.insertInputForShowPath("1", path.firstNode); + // await codeGraph.insertInputForShowPath("2", path.secondNode); + // const result = await codeGraph.getGraphDetails(); + // const firstNodeRes = findNodeByName(result.elements.nodes, path.firstNode); + // const secondNodeRes = findNodeByName(result.elements.nodes, path.secondNode); - const api = new ApiCalls(); - const response = await api.showPath(PROJECT_NAME ,firstNodeRes.id, secondNodeRes.id); - const callsRelationObject = response.result.paths[0].find(item => item.relation === "CALLS") - expect(callsRelationObject?.src_node).toBe(firstNodeRes.id); - expect(callsRelationObject?.dest_node).toBe(secondNodeRes.id); - }); - }) - - test(`Verify file download is triggered and saved after clicking download`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - const download = await codeGraph.downloadImage(); - const downloadPath = await download.path(); - expect(fs.existsSync(downloadPath)).toBe(true); - }) + // const api = new ApiCalls(); + // const response = await api.showPath(PROJECT_NAME ,firstNodeRes.id, secondNodeRes.id); + // const callsRelationObject = response.result.paths[0].find(item => item.relation === "CALLS") + // expect(callsRelationObject?.src_node).toBe(firstNodeRes.id); + // expect(callsRelationObject?.dest_node).toBe(secondNodeRes.id); + // }); + // }) + + // test(`Verify file download is triggered and saved after clicking download`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // const download = await codeGraph.downloadImage(); + // const downloadPath = await download.path(); + // expect(fs.existsSync(downloadPath)).toBe(true); + // }) nodes.slice(1,4).forEach((node) => { test(`Verify tooltip appears when hovering over node: ${node.nodeName}`, async () => { @@ -217,7 +217,7 @@ test.describe("Canvas tests", () => { await codeGraph.selectSearchBarOptionBtn("1"); await delay(2000); await codeGraph.hoverAtCanvasCenter(); - expect(await codeGraph.getTooltipVisibility()).toBe("visible"); + expect(await codeGraph.isNodeToolTipVisible()).toBe(true); }) }) From 1f0ec506a28f6cab4860c50aac43f74c7196002a Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Wed, 5 Mar 2025 13:07:30 +0200 Subject: [PATCH 094/189] add delay --- e2e/logic/POM/codeGraph.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 733e06c7..ec7d03ca 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -669,6 +669,7 @@ export default class CodeGraph extends BasePage { async isNodeToolTipVisible(): Promise { try { + await this.page.waitForTimeout(2000); const count = await this.nodeToolTip.count(); if (count === 0) { console.error("Tooltip not found"); From 5cdf9837839a1d45666d15a5a9d20b1409d7500b Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Wed, 5 Mar 2025 14:37:32 +0200 Subject: [PATCH 095/189] update test --- e2e/logic/POM/codeGraph.ts | 2 +- e2e/logic/utils.ts | 2 +- e2e/tests/canvas.spec.ts | 366 ++++++++++++++++++------------------ e2e/tests/searchBar.spec.ts | 2 +- 4 files changed, 186 insertions(+), 186 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index ec7d03ca..7ad8eb9a 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -669,7 +669,7 @@ export default class CodeGraph extends BasePage { async isNodeToolTipVisible(): Promise { try { - await this.page.waitForTimeout(2000); + await this.page.waitForTimeout(10000); const count = await this.nodeToolTip.count(); if (count === 0) { console.error("Tooltip not found"); diff --git a/e2e/logic/utils.ts b/e2e/logic/utils.ts index c1e270af..16c65161 100644 --- a/e2e/logic/utils.ts +++ b/e2e/logic/utils.ts @@ -34,7 +34,7 @@ export const waitForStableText = async (locator: Locator, timeout: number = 5000 return stableText; }; -export const waitForElementToBeVisible = async (locator:Locator,time=500,retry=5):Promise => { +export const waitForElementToBeVisible = async (locator:Locator,time=500,retry=10):Promise => { while(retry > 0){ if(await locator.isVisible()){ diff --git a/e2e/tests/canvas.spec.ts b/e2e/tests/canvas.spec.ts index 3785b80c..979a255a 100644 --- a/e2e/tests/canvas.spec.ts +++ b/e2e/tests/canvas.spec.ts @@ -19,193 +19,193 @@ test.describe("Canvas tests", () => { await browser.closeBrowser(); }); - // test(`Verify zoom in functionality on canvas`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // const initialGraph = await codeGraph.getCanvasScaling(); - // await codeGraph.clickZoomIn(); - // await codeGraph.clickZoomIn(); - // const updatedGraph = await codeGraph.getCanvasScaling(); - // expect(updatedGraph.scaleX).toBeGreaterThan(initialGraph.scaleX) - // expect(updatedGraph.scaleY).toBeGreaterThan(initialGraph.scaleY) - // }) - - // test(`Verify zoom out functionality on canvas`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // const initialGraph = await codeGraph.getCanvasScaling(); - // await codeGraph.clickZoomOut(); - // await codeGraph.clickZoomOut(); - // const updatedGraph = await codeGraph.getCanvasScaling(); - // expect(updatedGraph.scaleX).toBeLessThan(initialGraph.scaleX) - // expect(updatedGraph.scaleY).toBeLessThan(initialGraph.scaleY) - // }) - - // test(`Verify center graph button centers nodes in canvas`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // await codeGraph.clickCenter(); - // const initialGraph = await codeGraph.getCanvasScaling(); - // await codeGraph.clickZoomOut(); - // await codeGraph.clickZoomOut(); - // await codeGraph.clickCenter(); - // const updatedGraph = await codeGraph.getCanvasScaling(); - // expect(Math.abs(initialGraph.scaleX - updatedGraph.scaleX)).toBeLessThanOrEqual(0.1); - // expect(Math.abs(initialGraph.scaleY - updatedGraph.scaleY)).toBeLessThanOrEqual(0.1); - // }) - - // nodes.slice(0,2).forEach((node) => { - // test(`Validate node hide functionality via element menu in canvas for ${node.nodeName}`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // const initialGraph = await codeGraph.getGraphDetails(); - // const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); - // const targetNode = findNodeByName(convertCoordinates, node.nodeName); - // await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); - // await codeGraph.clickOnRemoveNodeViaElementMenu(); - // const updatedGraph = await codeGraph.getGraphDetails(); - // const targetNodeForUpdateGraph = findNodeByName(updatedGraph.elements.nodes, node.nodeName); - // expect(targetNodeForUpdateGraph.visible).toBe(false); - // }); - // }) - - // nodes.slice(0,2).forEach((node) => { - // test(`Validate unhide node functionality after hiding a node in canvas for ${node.nodeName}`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // const initialGraph = await codeGraph.getGraphDetails(); - // const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); - // const targetNode = findNodeByName(convertCoordinates, node.nodeName); - // await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); - // await codeGraph.clickOnRemoveNodeViaElementMenu(); - // await codeGraph.clickOnUnhideNodesBtn(); - // const updatedGraph = await codeGraph.getGraphDetails(); - // const targetNodeForUpdateGraph = findNodeByName(updatedGraph.elements.nodes, node.nodeName); - // expect(targetNodeForUpdateGraph.visible).toBe(true); - // }); - // }) - - // categories.forEach((category, index) => { - // const checkboxIndex = index + 1; - // test(`Verify that unchecking the ${category} checkbox hides ${category} nodes on the canvas`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // await codeGraph.selectCodeGraphCheckbox(checkboxIndex.toString()); - // const result = await codeGraph.getGraphDetails(); - // const findItem = result.categories.find((item: { name: string; }) => item.name === category) - // expect(findItem.show).toBe(false) - // }); - // }) - - // nodesPath.forEach((path) => { - // test(`Verify "Clear graph" button resets canvas view for path ${path.firstNode} and ${path.secondNode}`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // await codeGraph.clickOnShowPathBtn(); - // await codeGraph.insertInputForShowPath("1", path.firstNode); - // await codeGraph.insertInputForShowPath("2", path.secondNode); - // const initialGraph = await codeGraph.getGraphDetails(); - // const firstNode = findNodeByName(initialGraph.elements.nodes, path.firstNode); - // const secondNode = findNodeByName(initialGraph.elements.nodes, path.secondNode); - // expect(firstNode.isPath).toBe(true); - // expect(secondNode.isPath).toBe(true); - // await codeGraph.clickOnClearGraphBtn(); - // const updateGraph = await codeGraph.getGraphDetails(); - // const firstNode1 = findNodeByName(updateGraph.elements.nodes, path.firstNode); - // const secondNode1 = findNodeByName(updateGraph.elements.nodes, path.secondNode); - // expect(firstNode1.isPath).toBe(false); - // expect(secondNode1.isPath).toBe(false); - // }); - // }) - - // graphs.forEach(({graphName}) => { - // test(`Verify selecting different graphs displays nodes in canvas - grpah: ${graphName}`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(graphName); - // const result = await codeGraph.getGraphDetails(); - // expect(result.elements.nodes.length).toBeGreaterThan(1); - // expect(result.elements.links.length).toBeGreaterThan(1); - // }); - // }) + test(`Verify zoom in functionality on canvas`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + const initialGraph = await codeGraph.getCanvasScaling(); + await codeGraph.clickZoomIn(); + await codeGraph.clickZoomIn(); + const updatedGraph = await codeGraph.getCanvasScaling(); + expect(updatedGraph.scaleX).toBeGreaterThan(initialGraph.scaleX) + expect(updatedGraph.scaleY).toBeGreaterThan(initialGraph.scaleY) + }) + + test(`Verify zoom out functionality on canvas`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + const initialGraph = await codeGraph.getCanvasScaling(); + await codeGraph.clickZoomOut(); + await codeGraph.clickZoomOut(); + const updatedGraph = await codeGraph.getCanvasScaling(); + expect(updatedGraph.scaleX).toBeLessThan(initialGraph.scaleX) + expect(updatedGraph.scaleY).toBeLessThan(initialGraph.scaleY) + }) + + test(`Verify center graph button centers nodes in canvas`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + await codeGraph.clickCenter(); + const initialGraph = await codeGraph.getCanvasScaling(); + await codeGraph.clickZoomOut(); + await codeGraph.clickZoomOut(); + await codeGraph.clickCenter(); + const updatedGraph = await codeGraph.getCanvasScaling(); + expect(Math.abs(initialGraph.scaleX - updatedGraph.scaleX)).toBeLessThanOrEqual(0.1); + expect(Math.abs(initialGraph.scaleY - updatedGraph.scaleY)).toBeLessThanOrEqual(0.1); + }) + + nodes.slice(0,2).forEach((node) => { + test(`Validate node hide functionality via element menu in canvas for ${node.nodeName}`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + const initialGraph = await codeGraph.getGraphDetails(); + const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); + const targetNode = findNodeByName(convertCoordinates, node.nodeName); + await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); + await codeGraph.clickOnRemoveNodeViaElementMenu(); + const updatedGraph = await codeGraph.getGraphDetails(); + const targetNodeForUpdateGraph = findNodeByName(updatedGraph.elements.nodes, node.nodeName); + expect(targetNodeForUpdateGraph.visible).toBe(false); + }); + }) + + nodes.slice(0,2).forEach((node) => { + test(`Validate unhide node functionality after hiding a node in canvas for ${node.nodeName}`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + const initialGraph = await codeGraph.getGraphDetails(); + const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); + const targetNode = findNodeByName(convertCoordinates, node.nodeName); + await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); + await codeGraph.clickOnRemoveNodeViaElementMenu(); + await codeGraph.clickOnUnhideNodesBtn(); + const updatedGraph = await codeGraph.getGraphDetails(); + const targetNodeForUpdateGraph = findNodeByName(updatedGraph.elements.nodes, node.nodeName); + expect(targetNodeForUpdateGraph.visible).toBe(true); + }); + }) + + categories.forEach((category, index) => { + const checkboxIndex = index + 1; + test(`Verify that unchecking the ${category} checkbox hides ${category} nodes on the canvas`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + await codeGraph.selectCodeGraphCheckbox(checkboxIndex.toString()); + const result = await codeGraph.getGraphDetails(); + const findItem = result.categories.find((item: { name: string; }) => item.name === category) + expect(findItem.show).toBe(false) + }); + }) + + nodesPath.forEach((path) => { + test(`Verify "Clear graph" button resets canvas view for path ${path.firstNode} and ${path.secondNode}`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + await codeGraph.clickOnShowPathBtn(); + await codeGraph.insertInputForShowPath("1", path.firstNode); + await codeGraph.insertInputForShowPath("2", path.secondNode); + const initialGraph = await codeGraph.getGraphDetails(); + const firstNode = findNodeByName(initialGraph.elements.nodes, path.firstNode); + const secondNode = findNodeByName(initialGraph.elements.nodes, path.secondNode); + expect(firstNode.isPath).toBe(true); + expect(secondNode.isPath).toBe(true); + await codeGraph.clickOnClearGraphBtn(); + const updateGraph = await codeGraph.getGraphDetails(); + const firstNode1 = findNodeByName(updateGraph.elements.nodes, path.firstNode); + const secondNode1 = findNodeByName(updateGraph.elements.nodes, path.secondNode); + expect(firstNode1.isPath).toBe(false); + expect(secondNode1.isPath).toBe(false); + }); + }) + + graphs.forEach(({graphName}) => { + test(`Verify selecting different graphs displays nodes in canvas - grpah: ${graphName}`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(graphName); + const result = await codeGraph.getGraphDetails(); + expect(result.elements.nodes.length).toBeGreaterThan(1); + expect(result.elements.links.length).toBeGreaterThan(1); + }); + }) - // for (let index = 0; index < 3; index++) { - // const nodeIndex: number = index + 1; - // test(`Validate canvas node dragging for node: ${index}`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // const initialGraph = await codeGraph.getGraphDetails(); - // const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); - // await codeGraph.changeNodePosition(convertCoordinates[nodeIndex].screenX, convertCoordinates[nodeIndex].screenY); - // const updateGraph = await codeGraph.getGraphDetails(); - // expect(updateGraph.elements.nodes[nodeIndex].x).not.toBe(initialGraph.elements.nodes[nodeIndex].x); - // expect(updateGraph.elements.nodes[nodeIndex].y).not.toBe(initialGraph.elements.nodes[nodeIndex].y); - // }); - // } - - // test(`Validate node and edge counts in canvas match API data`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // const { nodes, edges } = await codeGraph.getMetricsPanelInfo(); - // const api = new ApiCalls(); - // const response = await api.projectInfo(PROJECT_NAME); - // expect(response.result.info.node_count).toEqual(parseInt(nodes)); - // expect(response.result.info.edge_count).toEqual(parseInt(edges)); - // }); + for (let index = 0; index < 3; index++) { + const nodeIndex: number = index + 1; + test(`Validate canvas node dragging for node: ${index}`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + const initialGraph = await codeGraph.getGraphDetails(); + const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); + await codeGraph.changeNodePosition(convertCoordinates[nodeIndex].screenX, convertCoordinates[nodeIndex].screenY); + const updateGraph = await codeGraph.getGraphDetails(); + expect(updateGraph.elements.nodes[nodeIndex].x).not.toBe(initialGraph.elements.nodes[nodeIndex].x); + expect(updateGraph.elements.nodes[nodeIndex].y).not.toBe(initialGraph.elements.nodes[nodeIndex].y); + }); + } + + test(`Validate node and edge counts in canvas match API data`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + const { nodes, edges } = await codeGraph.getMetricsPanelInfo(); + const api = new ApiCalls(); + const response = await api.projectInfo(PROJECT_NAME); + expect(response.result.info.node_count).toEqual(parseInt(nodes)); + expect(response.result.info.edge_count).toEqual(parseInt(edges)); + }); - // test(`Validate displayed nodes match API response after selecting a graph via UI`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // const graphData = await codeGraph.getGraphDetails(); - // const api = new ApiCalls(); - // const response = await api.getProject(PROJECT_NAME); - // const isMatching = graphData.elements.nodes.slice(0, 2).every( - // (node: any, index: number) => node.name === response.result.entities.nodes[index].properties.name - // ); - // expect(isMatching).toBe(true) - // }); - - // nodesPath.forEach(({firstNode, secondNode}) => { - // test(`Verify successful node path connection in canvas between ${firstNode} and ${secondNode} via UI`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // await codeGraph.clickOnShowPathBtn(); - // await codeGraph.insertInputForShowPath("1", firstNode); - // await codeGraph.insertInputForShowPath("2", secondNode); - // const result = await codeGraph.getGraphDetails(); - // const firstNodeRes = findNodeByName(result.elements.nodes, firstNode); - // const secondnodeRes = findNodeByName(result.elements.nodes, secondNode); - // expect(firstNodeRes.isPath).toBe(true) - // expect(secondnodeRes.isPath).toBe(true) - // }) - // }) - - // nodesPath.forEach((path) => { - // test(`Validate node path connection in canvas ui and confirm via api for path ${path.firstNode} and ${path.secondNode}`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // await codeGraph.clickOnShowPathBtn(); - // await codeGraph.insertInputForShowPath("1", path.firstNode); - // await codeGraph.insertInputForShowPath("2", path.secondNode); - // const result = await codeGraph.getGraphDetails(); - // const firstNodeRes = findNodeByName(result.elements.nodes, path.firstNode); - // const secondNodeRes = findNodeByName(result.elements.nodes, path.secondNode); + test(`Validate displayed nodes match API response after selecting a graph via UI`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + const graphData = await codeGraph.getGraphDetails(); + const api = new ApiCalls(); + const response = await api.getProject(PROJECT_NAME); + const isMatching = graphData.elements.nodes.slice(0, 2).every( + (node: any, index: number) => node.name === response.result.entities.nodes[index].properties.name + ); + expect(isMatching).toBe(true) + }); + + nodesPath.forEach(({firstNode, secondNode}) => { + test(`Verify successful node path connection in canvas between ${firstNode} and ${secondNode} via UI`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + await codeGraph.clickOnShowPathBtn(); + await codeGraph.insertInputForShowPath("1", firstNode); + await codeGraph.insertInputForShowPath("2", secondNode); + const result = await codeGraph.getGraphDetails(); + const firstNodeRes = findNodeByName(result.elements.nodes, firstNode); + const secondnodeRes = findNodeByName(result.elements.nodes, secondNode); + expect(firstNodeRes.isPath).toBe(true) + expect(secondnodeRes.isPath).toBe(true) + }) + }) + + nodesPath.forEach((path) => { + test(`Validate node path connection in canvas ui and confirm via api for path ${path.firstNode} and ${path.secondNode}`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + await codeGraph.clickOnShowPathBtn(); + await codeGraph.insertInputForShowPath("1", path.firstNode); + await codeGraph.insertInputForShowPath("2", path.secondNode); + const result = await codeGraph.getGraphDetails(); + const firstNodeRes = findNodeByName(result.elements.nodes, path.firstNode); + const secondNodeRes = findNodeByName(result.elements.nodes, path.secondNode); - // const api = new ApiCalls(); - // const response = await api.showPath(PROJECT_NAME ,firstNodeRes.id, secondNodeRes.id); - // const callsRelationObject = response.result.paths[0].find(item => item.relation === "CALLS") - // expect(callsRelationObject?.src_node).toBe(firstNodeRes.id); - // expect(callsRelationObject?.dest_node).toBe(secondNodeRes.id); - // }); - // }) - - // test(`Verify file download is triggered and saved after clicking download`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // const download = await codeGraph.downloadImage(); - // const downloadPath = await download.path(); - // expect(fs.existsSync(downloadPath)).toBe(true); - // }) + const api = new ApiCalls(); + const response = await api.showPath(PROJECT_NAME ,firstNodeRes.id, secondNodeRes.id); + const callsRelationObject = response.result.paths[0].find(item => item.relation === "CALLS") + expect(callsRelationObject?.src_node).toBe(firstNodeRes.id); + expect(callsRelationObject?.dest_node).toBe(secondNodeRes.id); + }); + }) + + test(`Verify file download is triggered and saved after clicking download`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + const download = await codeGraph.downloadImage(); + const downloadPath = await download.path(); + expect(fs.existsSync(downloadPath)).toBe(true); + }) nodes.slice(1,4).forEach((node) => { test(`Verify tooltip appears when hovering over node: ${node.nodeName}`, async () => { diff --git a/e2e/tests/searchBar.spec.ts b/e2e/tests/searchBar.spec.ts index 0642024b..e0cc33b6 100644 --- a/e2e/tests/searchBar.spec.ts +++ b/e2e/tests/searchBar.spec.ts @@ -83,7 +83,7 @@ test.describe("search bar tests", () => { await codeGraph.getGraphDetails(); await codeGraph.fillSearchBar(nodeName); await codeGraph.selectSearchBarOptionBtn("1"); - await delay(2000); + await delay(4000); await codeGraph.rightClickAtCanvasCenter(); expect(await codeGraph.getNodeDetailsHeader()).toContain(nodeName.toUpperCase()); }); From f79852e35a8e1e429b12612dbbd18214b7f12fe5 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Wed, 5 Mar 2025 14:57:09 +0200 Subject: [PATCH 096/189] update locator --- e2e/logic/POM/codeGraph.ts | 14 +- e2e/tests/canvas.spec.ts | 372 ++++++++++++++++++------------------- 2 files changed, 193 insertions(+), 193 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 7ad8eb9a..e0d93ce5 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -228,9 +228,9 @@ export default class CodeGraph extends BasePage { private get copyToClipboardNodePanelDetails(): Locator { return this.page.locator(`//div[@data-name='node-details-panel']//button[@title='Copy src to clipboard']`); } - - private get nodeToolTip(): Locator { - return this.page.locator("//div[contains(@class, 'graph-tooltip')]"); + + private get nodeToolTip(): (node: string) => Locator { + return (node: string) => this.page.locator(`//div[contains(@class, 'force-graph-container')]/div[contains(text(), '${node}')]`); } private get downloadImageBtn(): Locator { @@ -667,21 +667,21 @@ export default class CodeGraph extends BasePage { await this.page.mouse.move(centerX, centerY); } - async isNodeToolTipVisible(): Promise { + async isNodeToolTipVisible(node: string): Promise { try { await this.page.waitForTimeout(10000); - const count = await this.nodeToolTip.count(); + const count = await this.nodeToolTip(node).count(); if (count === 0) { console.error("Tooltip not found"); return false; } - const box = await this.nodeToolTip.boundingBox(); + const box = await this.nodeToolTip(node).boundingBox(); if (box && box.width > 0 && box.height > 0) { return true; } - return await this.nodeToolTip.evaluate(el => { + return await this.nodeToolTip(node).evaluate(el => { const style = getComputedStyle(el); return style.visibility === 'visible' && parseFloat(style.opacity) > 0; }); diff --git a/e2e/tests/canvas.spec.ts b/e2e/tests/canvas.spec.ts index 979a255a..eb827849 100644 --- a/e2e/tests/canvas.spec.ts +++ b/e2e/tests/canvas.spec.ts @@ -19,195 +19,195 @@ test.describe("Canvas tests", () => { await browser.closeBrowser(); }); - test(`Verify zoom in functionality on canvas`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - const initialGraph = await codeGraph.getCanvasScaling(); - await codeGraph.clickZoomIn(); - await codeGraph.clickZoomIn(); - const updatedGraph = await codeGraph.getCanvasScaling(); - expect(updatedGraph.scaleX).toBeGreaterThan(initialGraph.scaleX) - expect(updatedGraph.scaleY).toBeGreaterThan(initialGraph.scaleY) - }) - - test(`Verify zoom out functionality on canvas`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - const initialGraph = await codeGraph.getCanvasScaling(); - await codeGraph.clickZoomOut(); - await codeGraph.clickZoomOut(); - const updatedGraph = await codeGraph.getCanvasScaling(); - expect(updatedGraph.scaleX).toBeLessThan(initialGraph.scaleX) - expect(updatedGraph.scaleY).toBeLessThan(initialGraph.scaleY) - }) - - test(`Verify center graph button centers nodes in canvas`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - await codeGraph.clickCenter(); - const initialGraph = await codeGraph.getCanvasScaling(); - await codeGraph.clickZoomOut(); - await codeGraph.clickZoomOut(); - await codeGraph.clickCenter(); - const updatedGraph = await codeGraph.getCanvasScaling(); - expect(Math.abs(initialGraph.scaleX - updatedGraph.scaleX)).toBeLessThanOrEqual(0.1); - expect(Math.abs(initialGraph.scaleY - updatedGraph.scaleY)).toBeLessThanOrEqual(0.1); - }) - - nodes.slice(0,2).forEach((node) => { - test(`Validate node hide functionality via element menu in canvas for ${node.nodeName}`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - const initialGraph = await codeGraph.getGraphDetails(); - const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); - const targetNode = findNodeByName(convertCoordinates, node.nodeName); - await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); - await codeGraph.clickOnRemoveNodeViaElementMenu(); - const updatedGraph = await codeGraph.getGraphDetails(); - const targetNodeForUpdateGraph = findNodeByName(updatedGraph.elements.nodes, node.nodeName); - expect(targetNodeForUpdateGraph.visible).toBe(false); - }); - }) - - nodes.slice(0,2).forEach((node) => { - test(`Validate unhide node functionality after hiding a node in canvas for ${node.nodeName}`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - const initialGraph = await codeGraph.getGraphDetails(); - const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); - const targetNode = findNodeByName(convertCoordinates, node.nodeName); - await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); - await codeGraph.clickOnRemoveNodeViaElementMenu(); - await codeGraph.clickOnUnhideNodesBtn(); - const updatedGraph = await codeGraph.getGraphDetails(); - const targetNodeForUpdateGraph = findNodeByName(updatedGraph.elements.nodes, node.nodeName); - expect(targetNodeForUpdateGraph.visible).toBe(true); - }); - }) - - categories.forEach((category, index) => { - const checkboxIndex = index + 1; - test(`Verify that unchecking the ${category} checkbox hides ${category} nodes on the canvas`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - await codeGraph.selectCodeGraphCheckbox(checkboxIndex.toString()); - const result = await codeGraph.getGraphDetails(); - const findItem = result.categories.find((item: { name: string; }) => item.name === category) - expect(findItem.show).toBe(false) - }); - }) - - nodesPath.forEach((path) => { - test(`Verify "Clear graph" button resets canvas view for path ${path.firstNode} and ${path.secondNode}`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - await codeGraph.clickOnShowPathBtn(); - await codeGraph.insertInputForShowPath("1", path.firstNode); - await codeGraph.insertInputForShowPath("2", path.secondNode); - const initialGraph = await codeGraph.getGraphDetails(); - const firstNode = findNodeByName(initialGraph.elements.nodes, path.firstNode); - const secondNode = findNodeByName(initialGraph.elements.nodes, path.secondNode); - expect(firstNode.isPath).toBe(true); - expect(secondNode.isPath).toBe(true); - await codeGraph.clickOnClearGraphBtn(); - const updateGraph = await codeGraph.getGraphDetails(); - const firstNode1 = findNodeByName(updateGraph.elements.nodes, path.firstNode); - const secondNode1 = findNodeByName(updateGraph.elements.nodes, path.secondNode); - expect(firstNode1.isPath).toBe(false); - expect(secondNode1.isPath).toBe(false); - }); - }) - - graphs.forEach(({graphName}) => { - test(`Verify selecting different graphs displays nodes in canvas - grpah: ${graphName}`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(graphName); - const result = await codeGraph.getGraphDetails(); - expect(result.elements.nodes.length).toBeGreaterThan(1); - expect(result.elements.links.length).toBeGreaterThan(1); - }); - }) + // test(`Verify zoom in functionality on canvas`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // const initialGraph = await codeGraph.getCanvasScaling(); + // await codeGraph.clickZoomIn(); + // await codeGraph.clickZoomIn(); + // const updatedGraph = await codeGraph.getCanvasScaling(); + // expect(updatedGraph.scaleX).toBeGreaterThan(initialGraph.scaleX) + // expect(updatedGraph.scaleY).toBeGreaterThan(initialGraph.scaleY) + // }) + + // test(`Verify zoom out functionality on canvas`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // const initialGraph = await codeGraph.getCanvasScaling(); + // await codeGraph.clickZoomOut(); + // await codeGraph.clickZoomOut(); + // const updatedGraph = await codeGraph.getCanvasScaling(); + // expect(updatedGraph.scaleX).toBeLessThan(initialGraph.scaleX) + // expect(updatedGraph.scaleY).toBeLessThan(initialGraph.scaleY) + // }) + + // test(`Verify center graph button centers nodes in canvas`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // await codeGraph.clickCenter(); + // const initialGraph = await codeGraph.getCanvasScaling(); + // await codeGraph.clickZoomOut(); + // await codeGraph.clickZoomOut(); + // await codeGraph.clickCenter(); + // const updatedGraph = await codeGraph.getCanvasScaling(); + // expect(Math.abs(initialGraph.scaleX - updatedGraph.scaleX)).toBeLessThanOrEqual(0.1); + // expect(Math.abs(initialGraph.scaleY - updatedGraph.scaleY)).toBeLessThanOrEqual(0.1); + // }) + + // nodes.slice(0,2).forEach((node) => { + // test(`Validate node hide functionality via element menu in canvas for ${node.nodeName}`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // const initialGraph = await codeGraph.getGraphDetails(); + // const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); + // const targetNode = findNodeByName(convertCoordinates, node.nodeName); + // await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); + // await codeGraph.clickOnRemoveNodeViaElementMenu(); + // const updatedGraph = await codeGraph.getGraphDetails(); + // const targetNodeForUpdateGraph = findNodeByName(updatedGraph.elements.nodes, node.nodeName); + // expect(targetNodeForUpdateGraph.visible).toBe(false); + // }); + // }) + + // nodes.slice(0,2).forEach((node) => { + // test(`Validate unhide node functionality after hiding a node in canvas for ${node.nodeName}`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // const initialGraph = await codeGraph.getGraphDetails(); + // const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); + // const targetNode = findNodeByName(convertCoordinates, node.nodeName); + // await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); + // await codeGraph.clickOnRemoveNodeViaElementMenu(); + // await codeGraph.clickOnUnhideNodesBtn(); + // const updatedGraph = await codeGraph.getGraphDetails(); + // const targetNodeForUpdateGraph = findNodeByName(updatedGraph.elements.nodes, node.nodeName); + // expect(targetNodeForUpdateGraph.visible).toBe(true); + // }); + // }) + + // categories.forEach((category, index) => { + // const checkboxIndex = index + 1; + // test(`Verify that unchecking the ${category} checkbox hides ${category} nodes on the canvas`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // await codeGraph.selectCodeGraphCheckbox(checkboxIndex.toString()); + // const result = await codeGraph.getGraphDetails(); + // const findItem = result.categories.find((item: { name: string; }) => item.name === category) + // expect(findItem.show).toBe(false) + // }); + // }) + + // nodesPath.forEach((path) => { + // test(`Verify "Clear graph" button resets canvas view for path ${path.firstNode} and ${path.secondNode}`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // await codeGraph.clickOnShowPathBtn(); + // await codeGraph.insertInputForShowPath("1", path.firstNode); + // await codeGraph.insertInputForShowPath("2", path.secondNode); + // const initialGraph = await codeGraph.getGraphDetails(); + // const firstNode = findNodeByName(initialGraph.elements.nodes, path.firstNode); + // const secondNode = findNodeByName(initialGraph.elements.nodes, path.secondNode); + // expect(firstNode.isPath).toBe(true); + // expect(secondNode.isPath).toBe(true); + // await codeGraph.clickOnClearGraphBtn(); + // const updateGraph = await codeGraph.getGraphDetails(); + // const firstNode1 = findNodeByName(updateGraph.elements.nodes, path.firstNode); + // const secondNode1 = findNodeByName(updateGraph.elements.nodes, path.secondNode); + // expect(firstNode1.isPath).toBe(false); + // expect(secondNode1.isPath).toBe(false); + // }); + // }) + + // graphs.forEach(({graphName}) => { + // test(`Verify selecting different graphs displays nodes in canvas - grpah: ${graphName}`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(graphName); + // const result = await codeGraph.getGraphDetails(); + // expect(result.elements.nodes.length).toBeGreaterThan(1); + // expect(result.elements.links.length).toBeGreaterThan(1); + // }); + // }) - for (let index = 0; index < 3; index++) { - const nodeIndex: number = index + 1; - test(`Validate canvas node dragging for node: ${index}`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - const initialGraph = await codeGraph.getGraphDetails(); - const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); - await codeGraph.changeNodePosition(convertCoordinates[nodeIndex].screenX, convertCoordinates[nodeIndex].screenY); - const updateGraph = await codeGraph.getGraphDetails(); - expect(updateGraph.elements.nodes[nodeIndex].x).not.toBe(initialGraph.elements.nodes[nodeIndex].x); - expect(updateGraph.elements.nodes[nodeIndex].y).not.toBe(initialGraph.elements.nodes[nodeIndex].y); - }); - } - - test(`Validate node and edge counts in canvas match API data`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - const { nodes, edges } = await codeGraph.getMetricsPanelInfo(); - const api = new ApiCalls(); - const response = await api.projectInfo(PROJECT_NAME); - expect(response.result.info.node_count).toEqual(parseInt(nodes)); - expect(response.result.info.edge_count).toEqual(parseInt(edges)); - }); + // for (let index = 0; index < 3; index++) { + // const nodeIndex: number = index + 1; + // test(`Validate canvas node dragging for node: ${index}`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // const initialGraph = await codeGraph.getGraphDetails(); + // const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); + // await codeGraph.changeNodePosition(convertCoordinates[nodeIndex].screenX, convertCoordinates[nodeIndex].screenY); + // const updateGraph = await codeGraph.getGraphDetails(); + // expect(updateGraph.elements.nodes[nodeIndex].x).not.toBe(initialGraph.elements.nodes[nodeIndex].x); + // expect(updateGraph.elements.nodes[nodeIndex].y).not.toBe(initialGraph.elements.nodes[nodeIndex].y); + // }); + // } + + // test(`Validate node and edge counts in canvas match API data`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // const { nodes, edges } = await codeGraph.getMetricsPanelInfo(); + // const api = new ApiCalls(); + // const response = await api.projectInfo(PROJECT_NAME); + // expect(response.result.info.node_count).toEqual(parseInt(nodes)); + // expect(response.result.info.edge_count).toEqual(parseInt(edges)); + // }); - test(`Validate displayed nodes match API response after selecting a graph via UI`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - const graphData = await codeGraph.getGraphDetails(); - const api = new ApiCalls(); - const response = await api.getProject(PROJECT_NAME); - const isMatching = graphData.elements.nodes.slice(0, 2).every( - (node: any, index: number) => node.name === response.result.entities.nodes[index].properties.name - ); - expect(isMatching).toBe(true) - }); - - nodesPath.forEach(({firstNode, secondNode}) => { - test(`Verify successful node path connection in canvas between ${firstNode} and ${secondNode} via UI`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - await codeGraph.clickOnShowPathBtn(); - await codeGraph.insertInputForShowPath("1", firstNode); - await codeGraph.insertInputForShowPath("2", secondNode); - const result = await codeGraph.getGraphDetails(); - const firstNodeRes = findNodeByName(result.elements.nodes, firstNode); - const secondnodeRes = findNodeByName(result.elements.nodes, secondNode); - expect(firstNodeRes.isPath).toBe(true) - expect(secondnodeRes.isPath).toBe(true) - }) - }) - - nodesPath.forEach((path) => { - test(`Validate node path connection in canvas ui and confirm via api for path ${path.firstNode} and ${path.secondNode}`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - await codeGraph.clickOnShowPathBtn(); - await codeGraph.insertInputForShowPath("1", path.firstNode); - await codeGraph.insertInputForShowPath("2", path.secondNode); - const result = await codeGraph.getGraphDetails(); - const firstNodeRes = findNodeByName(result.elements.nodes, path.firstNode); - const secondNodeRes = findNodeByName(result.elements.nodes, path.secondNode); + // test(`Validate displayed nodes match API response after selecting a graph via UI`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // const graphData = await codeGraph.getGraphDetails(); + // const api = new ApiCalls(); + // const response = await api.getProject(PROJECT_NAME); + // const isMatching = graphData.elements.nodes.slice(0, 2).every( + // (node: any, index: number) => node.name === response.result.entities.nodes[index].properties.name + // ); + // expect(isMatching).toBe(true) + // }); + + // nodesPath.forEach(({firstNode, secondNode}) => { + // test(`Verify successful node path connection in canvas between ${firstNode} and ${secondNode} via UI`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // await codeGraph.clickOnShowPathBtn(); + // await codeGraph.insertInputForShowPath("1", firstNode); + // await codeGraph.insertInputForShowPath("2", secondNode); + // const result = await codeGraph.getGraphDetails(); + // const firstNodeRes = findNodeByName(result.elements.nodes, firstNode); + // const secondnodeRes = findNodeByName(result.elements.nodes, secondNode); + // expect(firstNodeRes.isPath).toBe(true) + // expect(secondnodeRes.isPath).toBe(true) + // }) + // }) + + // nodesPath.forEach((path) => { + // test(`Validate node path connection in canvas ui and confirm via api for path ${path.firstNode} and ${path.secondNode}`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // await codeGraph.clickOnShowPathBtn(); + // await codeGraph.insertInputForShowPath("1", path.firstNode); + // await codeGraph.insertInputForShowPath("2", path.secondNode); + // const result = await codeGraph.getGraphDetails(); + // const firstNodeRes = findNodeByName(result.elements.nodes, path.firstNode); + // const secondNodeRes = findNodeByName(result.elements.nodes, path.secondNode); - const api = new ApiCalls(); - const response = await api.showPath(PROJECT_NAME ,firstNodeRes.id, secondNodeRes.id); - const callsRelationObject = response.result.paths[0].find(item => item.relation === "CALLS") - expect(callsRelationObject?.src_node).toBe(firstNodeRes.id); - expect(callsRelationObject?.dest_node).toBe(secondNodeRes.id); - }); - }) - - test(`Verify file download is triggered and saved after clicking download`, async () => { - const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - await codeGraph.selectGraph(GRAPH_ID); - const download = await codeGraph.downloadImage(); - const downloadPath = await download.path(); - expect(fs.existsSync(downloadPath)).toBe(true); - }) - - nodes.slice(1,4).forEach((node) => { + // const api = new ApiCalls(); + // const response = await api.showPath(PROJECT_NAME ,firstNodeRes.id, secondNodeRes.id); + // const callsRelationObject = response.result.paths[0].find(item => item.relation === "CALLS") + // expect(callsRelationObject?.src_node).toBe(firstNodeRes.id); + // expect(callsRelationObject?.dest_node).toBe(secondNodeRes.id); + // }); + // }) + + // test(`Verify file download is triggered and saved after clicking download`, async () => { + // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + // await codeGraph.selectGraph(GRAPH_ID); + // const download = await codeGraph.downloadImage(); + // const downloadPath = await download.path(); + // expect(fs.existsSync(downloadPath)).toBe(true); + // }) + + nodes.slice(1,2).forEach((node) => { test(`Verify tooltip appears when hovering over node: ${node.nodeName}`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await browser.setPageToFullScreen(); @@ -217,7 +217,7 @@ test.describe("Canvas tests", () => { await codeGraph.selectSearchBarOptionBtn("1"); await delay(2000); await codeGraph.hoverAtCanvasCenter(); - expect(await codeGraph.isNodeToolTipVisible()).toBe(true); + expect(await codeGraph.isNodeToolTipVisible(node.nodeName)).toBe(true); }) }) From 07b5c4f905299e9d976c50d1abebce5594b20042 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Wed, 5 Mar 2025 16:05:55 +0200 Subject: [PATCH 097/189] update tests --- e2e/logic/POM/codeGraph.ts | 50 +++-- e2e/tests/canvas.spec.ts | 372 ++++++++++++++++++------------------ e2e/tests/searchBar.spec.ts | 2 +- 3 files changed, 216 insertions(+), 208 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index e0d93ce5..90536986 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -427,6 +427,7 @@ export default class CodeGraph extends BasePage { const button = this.searchBarOptionBtn(buttonNum); await button.waitFor({ state : "visible"}) await button.click(); + await this.page.waitForTimeout(4000); } async getSearchBarInputValue(): Promise { @@ -668,29 +669,36 @@ export default class CodeGraph extends BasePage { } async isNodeToolTipVisible(node: string): Promise { - try { - await this.page.waitForTimeout(10000); - const count = await this.nodeToolTip(node).count(); - if (count === 0) { - console.error("Tooltip not found"); - return false; - } + return await this.nodeToolTip(node).isVisible(); + } - const box = await this.nodeToolTip(node).boundingBox(); - if (box && box.width > 0 && box.height > 0) { - return true; - } + async waitForCanvasAnimationToEnd(timeout = 5000): Promise { + const canvasHandle = await this.canvasElement.elementHandle(); - return await this.nodeToolTip(node).evaluate(el => { - const style = getComputedStyle(el); - return style.visibility === 'visible' && parseFloat(style.opacity) > 0; - }); - } catch (error) { - console.error("Tooltip visibility check failed:", error); - return false; + if (!canvasHandle) { + throw new Error("Canvas element not found!"); } - } - - + await this.page.waitForFunction( + (canvas: HTMLElement) => { + const canvasElement = canvas as HTMLCanvasElement; + if (!canvasElement) return false; + + const ctx = canvasElement.getContext('2d'); + if (!ctx) return false; + + const getPixelData = () => ctx.getImageData(0, 0, canvasElement.width, canvasElement.height).data; + const imageData1 = getPixelData(); + + return new Promise((resolve) => { + setTimeout(() => { + const imageData2 = getPixelData(); + resolve(JSON.stringify(imageData1) === JSON.stringify(imageData2)); + }, 500); + }); + }, + canvasHandle as unknown as HTMLElement, + { timeout } + ); + } } diff --git a/e2e/tests/canvas.spec.ts b/e2e/tests/canvas.spec.ts index eb827849..aededeb6 100644 --- a/e2e/tests/canvas.spec.ts +++ b/e2e/tests/canvas.spec.ts @@ -19,195 +19,195 @@ test.describe("Canvas tests", () => { await browser.closeBrowser(); }); - // test(`Verify zoom in functionality on canvas`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // const initialGraph = await codeGraph.getCanvasScaling(); - // await codeGraph.clickZoomIn(); - // await codeGraph.clickZoomIn(); - // const updatedGraph = await codeGraph.getCanvasScaling(); - // expect(updatedGraph.scaleX).toBeGreaterThan(initialGraph.scaleX) - // expect(updatedGraph.scaleY).toBeGreaterThan(initialGraph.scaleY) - // }) - - // test(`Verify zoom out functionality on canvas`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // const initialGraph = await codeGraph.getCanvasScaling(); - // await codeGraph.clickZoomOut(); - // await codeGraph.clickZoomOut(); - // const updatedGraph = await codeGraph.getCanvasScaling(); - // expect(updatedGraph.scaleX).toBeLessThan(initialGraph.scaleX) - // expect(updatedGraph.scaleY).toBeLessThan(initialGraph.scaleY) - // }) - - // test(`Verify center graph button centers nodes in canvas`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // await codeGraph.clickCenter(); - // const initialGraph = await codeGraph.getCanvasScaling(); - // await codeGraph.clickZoomOut(); - // await codeGraph.clickZoomOut(); - // await codeGraph.clickCenter(); - // const updatedGraph = await codeGraph.getCanvasScaling(); - // expect(Math.abs(initialGraph.scaleX - updatedGraph.scaleX)).toBeLessThanOrEqual(0.1); - // expect(Math.abs(initialGraph.scaleY - updatedGraph.scaleY)).toBeLessThanOrEqual(0.1); - // }) - - // nodes.slice(0,2).forEach((node) => { - // test(`Validate node hide functionality via element menu in canvas for ${node.nodeName}`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // const initialGraph = await codeGraph.getGraphDetails(); - // const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); - // const targetNode = findNodeByName(convertCoordinates, node.nodeName); - // await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); - // await codeGraph.clickOnRemoveNodeViaElementMenu(); - // const updatedGraph = await codeGraph.getGraphDetails(); - // const targetNodeForUpdateGraph = findNodeByName(updatedGraph.elements.nodes, node.nodeName); - // expect(targetNodeForUpdateGraph.visible).toBe(false); - // }); - // }) - - // nodes.slice(0,2).forEach((node) => { - // test(`Validate unhide node functionality after hiding a node in canvas for ${node.nodeName}`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // const initialGraph = await codeGraph.getGraphDetails(); - // const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); - // const targetNode = findNodeByName(convertCoordinates, node.nodeName); - // await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); - // await codeGraph.clickOnRemoveNodeViaElementMenu(); - // await codeGraph.clickOnUnhideNodesBtn(); - // const updatedGraph = await codeGraph.getGraphDetails(); - // const targetNodeForUpdateGraph = findNodeByName(updatedGraph.elements.nodes, node.nodeName); - // expect(targetNodeForUpdateGraph.visible).toBe(true); - // }); - // }) - - // categories.forEach((category, index) => { - // const checkboxIndex = index + 1; - // test(`Verify that unchecking the ${category} checkbox hides ${category} nodes on the canvas`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // await codeGraph.selectCodeGraphCheckbox(checkboxIndex.toString()); - // const result = await codeGraph.getGraphDetails(); - // const findItem = result.categories.find((item: { name: string; }) => item.name === category) - // expect(findItem.show).toBe(false) - // }); - // }) - - // nodesPath.forEach((path) => { - // test(`Verify "Clear graph" button resets canvas view for path ${path.firstNode} and ${path.secondNode}`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // await codeGraph.clickOnShowPathBtn(); - // await codeGraph.insertInputForShowPath("1", path.firstNode); - // await codeGraph.insertInputForShowPath("2", path.secondNode); - // const initialGraph = await codeGraph.getGraphDetails(); - // const firstNode = findNodeByName(initialGraph.elements.nodes, path.firstNode); - // const secondNode = findNodeByName(initialGraph.elements.nodes, path.secondNode); - // expect(firstNode.isPath).toBe(true); - // expect(secondNode.isPath).toBe(true); - // await codeGraph.clickOnClearGraphBtn(); - // const updateGraph = await codeGraph.getGraphDetails(); - // const firstNode1 = findNodeByName(updateGraph.elements.nodes, path.firstNode); - // const secondNode1 = findNodeByName(updateGraph.elements.nodes, path.secondNode); - // expect(firstNode1.isPath).toBe(false); - // expect(secondNode1.isPath).toBe(false); - // }); - // }) - - // graphs.forEach(({graphName}) => { - // test(`Verify selecting different graphs displays nodes in canvas - grpah: ${graphName}`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(graphName); - // const result = await codeGraph.getGraphDetails(); - // expect(result.elements.nodes.length).toBeGreaterThan(1); - // expect(result.elements.links.length).toBeGreaterThan(1); - // }); - // }) + test(`Verify zoom in functionality on canvas`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + const initialGraph = await codeGraph.getCanvasScaling(); + await codeGraph.clickZoomIn(); + await codeGraph.clickZoomIn(); + const updatedGraph = await codeGraph.getCanvasScaling(); + expect(updatedGraph.scaleX).toBeGreaterThan(initialGraph.scaleX) + expect(updatedGraph.scaleY).toBeGreaterThan(initialGraph.scaleY) + }) + + test(`Verify zoom out functionality on canvas`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + const initialGraph = await codeGraph.getCanvasScaling(); + await codeGraph.clickZoomOut(); + await codeGraph.clickZoomOut(); + const updatedGraph = await codeGraph.getCanvasScaling(); + expect(updatedGraph.scaleX).toBeLessThan(initialGraph.scaleX) + expect(updatedGraph.scaleY).toBeLessThan(initialGraph.scaleY) + }) + + test(`Verify center graph button centers nodes in canvas`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + await codeGraph.clickCenter(); + const initialGraph = await codeGraph.getCanvasScaling(); + await codeGraph.clickZoomOut(); + await codeGraph.clickZoomOut(); + await codeGraph.clickCenter(); + const updatedGraph = await codeGraph.getCanvasScaling(); + expect(Math.abs(initialGraph.scaleX - updatedGraph.scaleX)).toBeLessThanOrEqual(0.1); + expect(Math.abs(initialGraph.scaleY - updatedGraph.scaleY)).toBeLessThanOrEqual(0.1); + }) + + nodes.slice(0,2).forEach((node) => { + test(`Validate node hide functionality via element menu in canvas for ${node.nodeName}`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + const initialGraph = await codeGraph.getGraphDetails(); + const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); + const targetNode = findNodeByName(convertCoordinates, node.nodeName); + await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); + await codeGraph.clickOnRemoveNodeViaElementMenu(); + const updatedGraph = await codeGraph.getGraphDetails(); + const targetNodeForUpdateGraph = findNodeByName(updatedGraph.elements.nodes, node.nodeName); + expect(targetNodeForUpdateGraph.visible).toBe(false); + }); + }) + + nodes.slice(0,2).forEach((node) => { + test(`Validate unhide node functionality after hiding a node in canvas for ${node.nodeName}`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + const initialGraph = await codeGraph.getGraphDetails(); + const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); + const targetNode = findNodeByName(convertCoordinates, node.nodeName); + await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); + await codeGraph.clickOnRemoveNodeViaElementMenu(); + await codeGraph.clickOnUnhideNodesBtn(); + const updatedGraph = await codeGraph.getGraphDetails(); + const targetNodeForUpdateGraph = findNodeByName(updatedGraph.elements.nodes, node.nodeName); + expect(targetNodeForUpdateGraph.visible).toBe(true); + }); + }) + + categories.forEach((category, index) => { + const checkboxIndex = index + 1; + test(`Verify that unchecking the ${category} checkbox hides ${category} nodes on the canvas`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + await codeGraph.selectCodeGraphCheckbox(checkboxIndex.toString()); + const result = await codeGraph.getGraphDetails(); + const findItem = result.categories.find((item: { name: string; }) => item.name === category) + expect(findItem.show).toBe(false) + }); + }) + + nodesPath.forEach((path) => { + test(`Verify "Clear graph" button resets canvas view for path ${path.firstNode} and ${path.secondNode}`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + await codeGraph.clickOnShowPathBtn(); + await codeGraph.insertInputForShowPath("1", path.firstNode); + await codeGraph.insertInputForShowPath("2", path.secondNode); + const initialGraph = await codeGraph.getGraphDetails(); + const firstNode = findNodeByName(initialGraph.elements.nodes, path.firstNode); + const secondNode = findNodeByName(initialGraph.elements.nodes, path.secondNode); + expect(firstNode.isPath).toBe(true); + expect(secondNode.isPath).toBe(true); + await codeGraph.clickOnClearGraphBtn(); + const updateGraph = await codeGraph.getGraphDetails(); + const firstNode1 = findNodeByName(updateGraph.elements.nodes, path.firstNode); + const secondNode1 = findNodeByName(updateGraph.elements.nodes, path.secondNode); + expect(firstNode1.isPath).toBe(false); + expect(secondNode1.isPath).toBe(false); + }); + }) + + graphs.forEach(({graphName}) => { + test(`Verify selecting different graphs displays nodes in canvas - grpah: ${graphName}`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(graphName); + const result = await codeGraph.getGraphDetails(); + expect(result.elements.nodes.length).toBeGreaterThan(1); + expect(result.elements.links.length).toBeGreaterThan(1); + }); + }) - // for (let index = 0; index < 3; index++) { - // const nodeIndex: number = index + 1; - // test(`Validate canvas node dragging for node: ${index}`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // const initialGraph = await codeGraph.getGraphDetails(); - // const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); - // await codeGraph.changeNodePosition(convertCoordinates[nodeIndex].screenX, convertCoordinates[nodeIndex].screenY); - // const updateGraph = await codeGraph.getGraphDetails(); - // expect(updateGraph.elements.nodes[nodeIndex].x).not.toBe(initialGraph.elements.nodes[nodeIndex].x); - // expect(updateGraph.elements.nodes[nodeIndex].y).not.toBe(initialGraph.elements.nodes[nodeIndex].y); - // }); - // } - - // test(`Validate node and edge counts in canvas match API data`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // const { nodes, edges } = await codeGraph.getMetricsPanelInfo(); - // const api = new ApiCalls(); - // const response = await api.projectInfo(PROJECT_NAME); - // expect(response.result.info.node_count).toEqual(parseInt(nodes)); - // expect(response.result.info.edge_count).toEqual(parseInt(edges)); - // }); + for (let index = 0; index < 3; index++) { + const nodeIndex: number = index + 1; + test(`Validate canvas node dragging for node: ${index}`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + const initialGraph = await codeGraph.getGraphDetails(); + const convertCoordinates = await codeGraph.transformNodeCoordinates(initialGraph); + await codeGraph.changeNodePosition(convertCoordinates[nodeIndex].screenX, convertCoordinates[nodeIndex].screenY); + const updateGraph = await codeGraph.getGraphDetails(); + expect(updateGraph.elements.nodes[nodeIndex].x).not.toBe(initialGraph.elements.nodes[nodeIndex].x); + expect(updateGraph.elements.nodes[nodeIndex].y).not.toBe(initialGraph.elements.nodes[nodeIndex].y); + }); + } + + test(`Validate node and edge counts in canvas match API data`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + const { nodes, edges } = await codeGraph.getMetricsPanelInfo(); + const api = new ApiCalls(); + const response = await api.projectInfo(PROJECT_NAME); + expect(response.result.info.node_count).toEqual(parseInt(nodes)); + expect(response.result.info.edge_count).toEqual(parseInt(edges)); + }); - // test(`Validate displayed nodes match API response after selecting a graph via UI`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // const graphData = await codeGraph.getGraphDetails(); - // const api = new ApiCalls(); - // const response = await api.getProject(PROJECT_NAME); - // const isMatching = graphData.elements.nodes.slice(0, 2).every( - // (node: any, index: number) => node.name === response.result.entities.nodes[index].properties.name - // ); - // expect(isMatching).toBe(true) - // }); - - // nodesPath.forEach(({firstNode, secondNode}) => { - // test(`Verify successful node path connection in canvas between ${firstNode} and ${secondNode} via UI`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // await codeGraph.clickOnShowPathBtn(); - // await codeGraph.insertInputForShowPath("1", firstNode); - // await codeGraph.insertInputForShowPath("2", secondNode); - // const result = await codeGraph.getGraphDetails(); - // const firstNodeRes = findNodeByName(result.elements.nodes, firstNode); - // const secondnodeRes = findNodeByName(result.elements.nodes, secondNode); - // expect(firstNodeRes.isPath).toBe(true) - // expect(secondnodeRes.isPath).toBe(true) - // }) - // }) - - // nodesPath.forEach((path) => { - // test(`Validate node path connection in canvas ui and confirm via api for path ${path.firstNode} and ${path.secondNode}`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // await codeGraph.clickOnShowPathBtn(); - // await codeGraph.insertInputForShowPath("1", path.firstNode); - // await codeGraph.insertInputForShowPath("2", path.secondNode); - // const result = await codeGraph.getGraphDetails(); - // const firstNodeRes = findNodeByName(result.elements.nodes, path.firstNode); - // const secondNodeRes = findNodeByName(result.elements.nodes, path.secondNode); + test(`Validate displayed nodes match API response after selecting a graph via UI`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + const graphData = await codeGraph.getGraphDetails(); + const api = new ApiCalls(); + const response = await api.getProject(PROJECT_NAME); + const isMatching = graphData.elements.nodes.slice(0, 2).every( + (node: any, index: number) => node.name === response.result.entities.nodes[index].properties.name + ); + expect(isMatching).toBe(true) + }); + + nodesPath.forEach(({firstNode, secondNode}) => { + test(`Verify successful node path connection in canvas between ${firstNode} and ${secondNode} via UI`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + await codeGraph.clickOnShowPathBtn(); + await codeGraph.insertInputForShowPath("1", firstNode); + await codeGraph.insertInputForShowPath("2", secondNode); + const result = await codeGraph.getGraphDetails(); + const firstNodeRes = findNodeByName(result.elements.nodes, firstNode); + const secondnodeRes = findNodeByName(result.elements.nodes, secondNode); + expect(firstNodeRes.isPath).toBe(true) + expect(secondnodeRes.isPath).toBe(true) + }) + }) + + nodesPath.forEach((path) => { + test(`Validate node path connection in canvas ui and confirm via api for path ${path.firstNode} and ${path.secondNode}`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + await codeGraph.clickOnShowPathBtn(); + await codeGraph.insertInputForShowPath("1", path.firstNode); + await codeGraph.insertInputForShowPath("2", path.secondNode); + const result = await codeGraph.getGraphDetails(); + const firstNodeRes = findNodeByName(result.elements.nodes, path.firstNode); + const secondNodeRes = findNodeByName(result.elements.nodes, path.secondNode); - // const api = new ApiCalls(); - // const response = await api.showPath(PROJECT_NAME ,firstNodeRes.id, secondNodeRes.id); - // const callsRelationObject = response.result.paths[0].find(item => item.relation === "CALLS") - // expect(callsRelationObject?.src_node).toBe(firstNodeRes.id); - // expect(callsRelationObject?.dest_node).toBe(secondNodeRes.id); - // }); - // }) - - // test(`Verify file download is triggered and saved after clicking download`, async () => { - // const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); - // await codeGraph.selectGraph(GRAPH_ID); - // const download = await codeGraph.downloadImage(); - // const downloadPath = await download.path(); - // expect(fs.existsSync(downloadPath)).toBe(true); - // }) - - nodes.slice(1,2).forEach((node) => { + const api = new ApiCalls(); + const response = await api.showPath(PROJECT_NAME ,firstNodeRes.id, secondNodeRes.id); + const callsRelationObject = response.result.paths[0].find(item => item.relation === "CALLS") + expect(callsRelationObject?.src_node).toBe(firstNodeRes.id); + expect(callsRelationObject?.dest_node).toBe(secondNodeRes.id); + }); + }) + + test(`Verify file download is triggered and saved after clicking download`, async () => { + const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await codeGraph.selectGraph(GRAPH_ID); + const download = await codeGraph.downloadImage(); + const downloadPath = await download.path(); + expect(fs.existsSync(downloadPath)).toBe(true); + }) + + nodes.forEach((node) => { test(`Verify tooltip appears when hovering over node: ${node.nodeName}`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await browser.setPageToFullScreen(); @@ -215,7 +215,7 @@ test.describe("Canvas tests", () => { await codeGraph.getGraphDetails(); await codeGraph.fillSearchBar(node.nodeName); await codeGraph.selectSearchBarOptionBtn("1"); - await delay(2000); + await codeGraph.waitForCanvasAnimationToEnd(); await codeGraph.hoverAtCanvasCenter(); expect(await codeGraph.isNodeToolTipVisible(node.nodeName)).toBe(true); }) diff --git a/e2e/tests/searchBar.spec.ts b/e2e/tests/searchBar.spec.ts index e0cc33b6..a7d73e8e 100644 --- a/e2e/tests/searchBar.spec.ts +++ b/e2e/tests/searchBar.spec.ts @@ -83,7 +83,7 @@ test.describe("search bar tests", () => { await codeGraph.getGraphDetails(); await codeGraph.fillSearchBar(nodeName); await codeGraph.selectSearchBarOptionBtn("1"); - await delay(4000); + await codeGraph.waitForCanvasAnimationToEnd(); await codeGraph.rightClickAtCanvasCenter(); expect(await codeGraph.getNodeDetailsHeader()).toContain(nodeName.toUpperCase()); }); From 09ec36cd71a0fc2e0812146d87cd02a376fd5efd Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Wed, 5 Mar 2025 16:12:52 +0200 Subject: [PATCH 098/189] Update codeGraph.ts --- e2e/logic/POM/codeGraph.ts | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 90536986..f3718e0a 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -680,25 +680,22 @@ export default class CodeGraph extends BasePage { } await this.page.waitForFunction( - (canvas: HTMLElement) => { - const canvasElement = canvas as HTMLCanvasElement; - if (!canvasElement) return false; - - const ctx = canvasElement.getContext('2d'); + (canvas) => { + const ctx = (canvas as HTMLCanvasElement).getContext('2d'); if (!ctx) return false; - const getPixelData = () => ctx.getImageData(0, 0, canvasElement.width, canvasElement.height).data; - const imageData1 = getPixelData(); + const imageData1 = ctx.getImageData(0, 0, (canvas as HTMLCanvasElement).width, (canvas as HTMLCanvasElement).height).data; return new Promise((resolve) => { setTimeout(() => { - const imageData2 = getPixelData(); + const imageData2 = ctx.getImageData(0, 0, (canvas as HTMLCanvasElement).width, (canvas as HTMLCanvasElement).height).data; resolve(JSON.stringify(imageData1) === JSON.stringify(imageData2)); }, 500); }); }, - canvasHandle as unknown as HTMLElement, + canvasHandle as any, { timeout } ); - } + } + } From 9fee1e696797304872d6bd93e2ec602d542dd6ff Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Mon, 10 Mar 2025 11:05:19 +0200 Subject: [PATCH 099/189] fix build --- app/components/code-graph.tsx | 39 +- package-lock.json | 2298 ++++++++++++++++----------------- 2 files changed, 1130 insertions(+), 1207 deletions(-) diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 78ca6ac5..623f3843 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -2,7 +2,7 @@ import { Dispatch, SetStateAction, useEffect, useRef, useState } from "react"; import { Graph, GraphData, Node, Link } from "./model"; import { Toolbar } from "./toolbar"; import { Labels } from "./labels"; -import { GitFork, Search, X } from "lucide-react"; +import { Download, GitFork, Search, X } from "lucide-react"; import ElementMenu from "./elementMenu"; import Combobox from "./combobox"; import { toast } from '@/components/ui/use-toast'; @@ -303,43 +303,6 @@ export function CodeGraph({ }
-
-
-

{nodesCount} Nodes

-

{edgesCount} Edges

-
-
- { - commitIndex !== commits.length && -
-
- -

Display Changes

-
-
-
-

Were added

-
-
-
-

Were edited

-
-
- } - - -
-
=10" }, @@ -46,9 +65,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz", - "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", + "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -56,50 +75,28 @@ "node": ">=6.9.0" } }, - "node_modules/@emnapi/runtime": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz", - "integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", - "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, + "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.4.3" + "eslint-visitor-keys": "^3.3.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "funding": { - "url": "https://opencollective.com/eslint" - }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/@eslint-community/regexpp": { "version": "4.12.1", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } @@ -118,10 +115,19 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/config-helpers": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.1.0.tgz", + "integrity": "sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/core": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.11.0.tgz", - "integrity": "sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", + "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.15" @@ -131,9 +137,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", - "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.0.tgz", + "integrity": "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -154,9 +160,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.20.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.20.0.tgz", - "integrity": "sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ==", + "version": "9.22.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.22.0.tgz", + "integrity": "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -172,30 +178,18 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", - "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz", + "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==", "dev": true, "dependencies": { - "@eslint/core": "^0.10.0", + "@eslint/core": "^0.12.0", "levn": "^0.4.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", - "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, "node_modules/@floating-ui/core": { "version": "1.6.9", "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz", @@ -235,6 +229,7 @@ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=18.18.0" } @@ -244,6 +239,7 @@ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" @@ -257,6 +253,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=18.18" }, @@ -270,6 +267,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -279,9 +277,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", - "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", + "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", "dev": true, "engines": { "node": ">=18.18" @@ -291,123 +289,6 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", - "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.0.4" - } - }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", - "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.0.4" - } - }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", - "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", - "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", - "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", - "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", - "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", - "cpu": [ - "s390x" - ], - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, "node_modules/@img/sharp-libvips-linux-x64": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", @@ -423,21 +304,6 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", - "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", @@ -453,69 +319,6 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", - "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.0.5" - } - }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", - "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.0.4" - } - }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", - "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", - "cpu": [ - "s390x" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.0.4" - } - }, "node_modules/@img/sharp-linux-x64": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", @@ -537,27 +340,6 @@ "@img/sharp-libvips-linux-x64": "1.0.4" } }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", - "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" - } - }, "node_modules/@img/sharp-linuxmusl-x64": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", @@ -579,64 +361,11 @@ "@img/sharp-libvips-linuxmusl-x64": "1.0.4" } }, - "node_modules/@img/sharp-wasm32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", - "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", - "cpu": [ - "wasm32" - ], - "optional": true, - "dependencies": { - "@emnapi/runtime": "^1.2.0" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", - "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", - "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -649,10 +378,38 @@ "node": ">=12" } }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -666,6 +423,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -674,6 +432,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -681,35 +440,65 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@next/env": { - "version": "15.1.7", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.1.7.tgz", - "integrity": "sha512-d9jnRrkuOH7Mhi+LHav2XW91HOgTAWHxjMPkXMGBc9B2b7614P7kjt8tAplRvJpbSt4nbO1lugcT/kAaWzjlLQ==" + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.2.1.tgz", + "integrity": "sha512-JmY0qvnPuS2NCWOz2bbby3Pe0VzdAQ7XpEB6uLIHmtXNfAsAO0KLQLkuAoc42Bxbo3/jMC3dcn9cdf+piCcG2Q==" }, "node_modules/@next/eslint-plugin-next": { - "version": "15.1.7", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.1.7.tgz", - "integrity": "sha512-kRP7RjSxfTO13NE317ek3mSGzoZlI33nc/i5hs1KaWpK+egs85xg0DJ4p32QEiHnR0mVjuUfhRIun7awqfL7pQ==", + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.2.1.tgz", + "integrity": "sha512-6ppeToFd02z38SllzWxayLxjjNfzvc7Wm07gQOKSLjyASvKcXjNStZrLXMHuaWkhjqxe+cnhb2uzfWXm1VEj/Q==", "dev": true, "dependencies": { "fast-glob": "3.3.1" } }, + "node_modules/@next/eslint-plugin-next/node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@next/swc-darwin-arm64": { - "version": "15.1.7", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.1.7.tgz", - "integrity": "sha512-hPFwzPJDpA8FGj7IKV3Yf1web3oz2YsR8du4amKw8d+jAOHfYHYFpMkoF6vgSY4W6vB29RtZEklK9ayinGiCmQ==", + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.2.1.tgz", + "integrity": "sha512-aWXT+5KEREoy3K5AKtiKwioeblmOvFFjd+F3dVleLvvLiQ/mD//jOOuUcx5hzcO9ISSw4lrqtUPntTpK32uXXQ==", "cpu": [ "arm64" ], @@ -722,9 +511,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "15.1.7", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.1.7.tgz", - "integrity": "sha512-2qoas+fO3OQKkU0PBUfwTiw/EYpN+kdAx62cePRyY1LqKtP09Vp5UcUntfZYajop5fDFTjSxCHfZVRxzi+9FYQ==", + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.2.1.tgz", + "integrity": "sha512-E/w8ervu4fcG5SkLhvn1NE/2POuDCDEy5gFbfhmnYXkyONZR68qbUlJlZwuN82o7BrBVAw+tkR8nTIjGiMW1jQ==", "cpu": [ "x64" ], @@ -737,9 +526,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.1.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.1.7.tgz", - "integrity": "sha512-sKLLwDX709mPdzxMnRIXLIT9zaX2w0GUlkLYQnKGoXeWUhcvpCrK+yevcwCJPdTdxZEUA0mOXGLdPsGkudGdnA==", + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.2.1.tgz", + "integrity": "sha512-gXDX5lIboebbjhiMT6kFgu4svQyjoSed6dHyjx5uZsjlvTwOAnZpn13w9XDaIMFFHw7K8CpBK7HfDKw0VZvUXQ==", "cpu": [ "arm64" ], @@ -752,9 +541,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.1.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.1.7.tgz", - "integrity": "sha512-zblK1OQbQWdC8fxdX4fpsHDw+VSpBPGEUX4PhSE9hkaWPrWoeIJn+baX53vbsbDRaDKd7bBNcXRovY1hEhFd7w==", + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.2.1.tgz", + "integrity": "sha512-3v0pF/adKZkBWfUffmB/ROa+QcNTrnmYG4/SS+r52HPwAK479XcWoES2I+7F7lcbqc7mTeVXrIvb4h6rR/iDKg==", "cpu": [ "arm64" ], @@ -767,9 +556,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.1.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.1.7.tgz", - "integrity": "sha512-GOzXutxuLvLHFDAPsMP2zDBMl1vfUHHpdNpFGhxu90jEzH6nNIgmtw/s1MDwpTOiM+MT5V8+I1hmVFeAUhkbgQ==", + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.2.1.tgz", + "integrity": "sha512-RbsVq2iB6KFJRZ2cHrU67jLVLKeuOIhnQB05ygu5fCNgg8oTewxweJE8XlLV+Ii6Y6u4EHwETdUiRNXIAfpBww==", "cpu": [ "x64" ], @@ -782,9 +571,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "15.1.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.1.7.tgz", - "integrity": "sha512-WrZ7jBhR7ATW1z5iEQ0ZJfE2twCNSXbpCSaAunF3BKcVeHFADSI/AW1y5Xt3DzTqPF1FzQlwQTewqetAABhZRQ==", + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.2.1.tgz", + "integrity": "sha512-QHsMLAyAIu6/fWjHmkN/F78EFPKmhQlyX5C8pRIS2RwVA7z+t9cTb0IaYWC3EHLOTjsU7MNQW+n2xGXr11QPpg==", "cpu": [ "x64" ], @@ -797,9 +586,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.1.7", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.1.7.tgz", - "integrity": "sha512-LDnj1f3OVbou1BqvvXVqouJZKcwq++mV2F+oFHptToZtScIEnhNRJAhJzqAtTE2dB31qDYL45xJwrc+bLeKM2Q==", + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.2.1.tgz", + "integrity": "sha512-Gk42XZXo1cE89i3hPLa/9KZ8OuupTjkDmhLaMKFohjf9brOeZVEa3BQy1J9s9TWUqPhgAEbwv6B2+ciGfe54Vw==", "cpu": [ "arm64" ], @@ -812,9 +601,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.1.7", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.1.7.tgz", - "integrity": "sha512-dC01f1quuf97viOfW05/K8XYv2iuBgAxJZl7mbCKEjMgdQl5JjAKJ0D2qMKZCgPWDeFbFT0Q0nYWwytEW0DWTQ==", + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.2.1.tgz", + "integrity": "sha512-YjqXCl8QGhVlMR8uBftWk0iTmvtntr41PhG1kvzGp0sUP/5ehTM+cwx25hKE54J0CRnHYjSGjSH3gkHEaHIN9g==", "cpu": [ "x64" ], @@ -830,6 +619,7 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -842,6 +632,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", "engines": { "node": ">= 8" } @@ -850,6 +641,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -858,31 +650,23 @@ "node": ">= 8" } }, - "node_modules/@nolyfill/is-core-module": { - "version": "1.0.39", - "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", - "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", - "dev": true, - "engines": { - "node": ">=12.4.0" - } - }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", "optional": true, "engines": { "node": ">=14" } }, "node_modules/@playwright/test": { - "version": "1.50.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.50.1.tgz", - "integrity": "sha512-Jii3aBg+CEDpgnuDxEp/h7BimHcUTDlpEtce89xEumlJ5ef2hqepZ+PWp1DDpYC/VO9fmWVI1IlEaoI5fK9FXQ==", + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.51.0.tgz", + "integrity": "sha512-dJ0dMbZeHhI+wb77+ljx/FeC8VBP6j/rj9OAojO08JI80wTZy6vRk9KvHKiDCUh4iMpEiseMgqRBIeW+eKX6RA==", "devOptional": true, "dependencies": { - "playwright": "1.50.1" + "playwright": "1.51.0" }, "bin": { "playwright": "cli.js" @@ -894,7 +678,8 @@ "node_modules/@radix-ui/number": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz", - "integrity": "sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==" + "integrity": "sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==", + "license": "MIT" }, "node_modules/@radix-ui/primitive": { "version": "1.1.1", @@ -977,23 +762,6 @@ } } }, - "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", - "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/@radix-ui/react-compose-refs": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", @@ -1057,6 +825,98 @@ } } }, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", + "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz", + "integrity": "sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg==", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-escape-keydown": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.6.tgz", + "integrity": "sha512-no3X7V5fD487wab/ZYSHXq3H37u4NVeLDKI/Ks724X/eEFSSEFYZxWgsIlr1UBeEyDaM29HM5x9p1Nv8DuTYPA==", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-menu": "2.1.6", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-controllable-state": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", + "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz", + "integrity": "sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-callback-ref": "1.1.0" + }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", @@ -1106,6 +966,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", + "license": "MIT", "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, @@ -1208,6 +1069,82 @@ "optional": true }, "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz", + "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz", + "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==", + "dependencies": { + "@radix-ui/react-slot": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-progress": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.2.tgz", + "integrity": "sha512-u1IgJFQ4zNAUTjGdDL5dcl/U8ntOR6jsnhxKb5RKp5Ozwl88xKR9EqRZOe/Mk8tnx0x5tNUe2F+MzsyjqMg0MA==", + "dependencies": { + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-primitive": "2.0.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.2.tgz", + "integrity": "sha512-zgMQWkNO169GtGqRvYrzb0Zf8NhMHS2DuEB/TiEmVnpr5OqPU3i8lfbxaAmC2J/KYuIQxyoQQ6DxepyXp61/xw==", "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-collection": "1.1.2", @@ -1363,6 +1300,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "license": "MIT", "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -1377,6 +1315,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "license": "MIT", "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.0" }, @@ -1411,6 +1350,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", + "license": "MIT", "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -1425,6 +1365,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz", "integrity": "sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==", + "license": "MIT", "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -1456,6 +1397,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", + "license": "MIT", "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, @@ -1473,6 +1415,8 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.2.tgz", "integrity": "sha512-1SzA4ns2M1aRlvxErqhLHsBHoS5eI5UUcI2awAMgGUp4LoaoWOKYmvqDY2s/tltuPkh3Yk77YF/r3IRj+Amx4Q==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.2" }, "peerDependencies": { "@types/react": "*", @@ -1501,10 +1445,11 @@ "dev": true }, "node_modules/@rushstack/eslint-patch": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.5.tgz", - "integrity": "sha512-kkKUDVlII2DQiKy7UstOR1ErJP8kUKAQ4oa+SQtM0K+lPdmmjj0YnnxBgtTVYH7mUKtbsxeFC9y0AmK7Yb78/A==", - "dev": true + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz", + "integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==", + "dev": true, + "license": "MIT" }, "node_modules/@swc/counter": { "version": "0.1.3", @@ -1528,7 +1473,8 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/hast": { "version": "2.3.10", @@ -1542,32 +1488,35 @@ "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==" + "version": "4.17.14", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.14.tgz", + "integrity": "sha512-jsxagdikDiDBeIRaPYtArcT8my4tN1og7MtMRquFT3XNA6axxyHDRUemqDz/taRDdOUn0GnGHRCuff4q48sW9A==" }, "node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", + "version": "22.13.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", + "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", "dev": true, "dependencies": { "undici-types": "~6.20.0" } }, "node_modules/@types/prop-types": { - "version": "15.7.14", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", - "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==" + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "license": "MIT" }, "node_modules/@types/react": { "version": "18.3.18", @@ -1607,20 +1556,20 @@ "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.24.0.tgz", - "integrity": "sha512-aFcXEJJCI4gUdXgoo/j9udUYIHgF23MFkg09LFz2dzEmU0+1Plk4rQWv/IYKvPHAtlkkGoB3m5e6oUp+JPsNaQ==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.13.0.tgz", + "integrity": "sha512-nQtBLiZYMUPkclSeC3id+x4uVd1SGtHuElTxL++SfP47jR0zfkZBJHc+gL4qPsgTuypz0k8Y2GheaDYn6Gy3rg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.24.0", - "@typescript-eslint/type-utils": "8.24.0", - "@typescript-eslint/utils": "8.24.0", - "@typescript-eslint/visitor-keys": "8.24.0", + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/type-utils": "8.13.0", + "@typescript-eslint/utils": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^1.3.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1631,20 +1580,24 @@ }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/@typescript-eslint/parser": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.24.0.tgz", - "integrity": "sha512-MFDaO9CYiard9j9VepMNa9MTcqVvSny2N4hkY6roquzj8pdCBRENhErrteaQuu7Yjn1ppk0v1/ZF9CG3KIlrTA==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.13.0.tgz", + "integrity": "sha512-w0xp+xGg8u/nONcGw1UXAr6cjCPU1w0XVyBs6Zqaj5eLmxkKQAByTdV/uGgNN5tVvN/kKpoQlP2cL7R+ajZZIQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.24.0", - "@typescript-eslint/types": "8.24.0", - "@typescript-eslint/typescript-estree": "8.24.0", - "@typescript-eslint/visitor-keys": "8.24.0", + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/typescript-estree": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", "debug": "^4.3.4" }, "engines": { @@ -1655,18 +1608,22 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.24.0.tgz", - "integrity": "sha512-HZIX0UByphEtdVBKaQBgTDdn9z16l4aTUz8e8zPQnyxwHBtf5vtl1L+OhH+m1FGV9DrRmoDuYKqzVrvWDcDozw==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.13.0.tgz", + "integrity": "sha512-XsGWww0odcUT0gJoBZ1DeulY1+jkaHUciUq4jKNv4cpInbvvrtDoyBH9rE/n2V29wQJPk8iCH1wipra9BhmiMA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.24.0", - "@typescript-eslint/visitor-keys": "8.24.0" + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1677,15 +1634,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.24.0.tgz", - "integrity": "sha512-8fitJudrnY8aq0F1wMiPM1UUgiXQRJ5i8tFjq9kGfRajU+dbPyOuHbl0qRopLEidy0MwqgTHDt6CnSeXanNIwA==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.13.0.tgz", + "integrity": "sha512-Rqnn6xXTR316fP4D2pohZenJnp+NwQ1mo7/JM+J1LWZENSLkJI8ID8QNtlvFeb0HnFSK94D6q0cnMX6SbE5/vA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.24.0", - "@typescript-eslint/utils": "8.24.0", + "@typescript-eslint/typescript-estree": "8.13.0", + "@typescript-eslint/utils": "8.13.0", "debug": "^4.3.4", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^1.3.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1694,15 +1651,16 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/@typescript-eslint/types": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.24.0.tgz", - "integrity": "sha512-VacJCBTyje7HGAw7xp11q439A+zeGG0p0/p2zsZwpnMzjPB5WteaWqt4g2iysgGFafrqvyLWqq6ZPZAOCoefCw==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.13.0.tgz", + "integrity": "sha512-4cyFErJetFLckcThRUFdReWJjVsPCqyBlJTi6IDEpc1GWCIIZRFxVppjWLIMcQhNGhdWJJRYFHpHoDWvMlDzng==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1713,19 +1671,19 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.24.0.tgz", - "integrity": "sha512-ITjYcP0+8kbsvT9bysygfIfb+hBj6koDsu37JZG7xrCiy3fPJyNmfVtaGsgTUSEuTzcvME5YI5uyL5LD1EV5ZQ==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.13.0.tgz", + "integrity": "sha512-v7SCIGmVsRK2Cy/LTLGN22uea6SaUIlpBcO/gnMGT/7zPtxp90bphcGf4fyrCQl3ZtiBKqVTG32hb668oIYy1g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.24.0", - "@typescript-eslint/visitor-keys": "8.24.0", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^1.3.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1733,46 +1691,20 @@ "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.8.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" + "balanced-match": "^1.0.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { @@ -1791,15 +1723,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.24.0.tgz", - "integrity": "sha512-07rLuUBElvvEb1ICnafYWr4hk8/U7X9RDCOqd9JcAMtjh/9oRmcfN4yGzbPVirgMR0+HLVHehmu19CWeh7fsmQ==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.13.0.tgz", + "integrity": "sha512-A1EeYOND6Uv250nybnLZapeXpYMl8tkzYUxqmoKAWnI4sei3ihf2XdZVd+vVOmHGcp3t+P7yRrNsyyiXTvShFQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.24.0", - "@typescript-eslint/types": "8.24.0", - "@typescript-eslint/typescript-estree": "8.24.0" + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/typescript-estree": "8.13.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1809,26 +1741,15 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "eslint": "^8.57.0 || ^9.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.24.0.tgz", - "integrity": "sha512-kArLq83QxGLbuHrTMoOEWO+l2MwsNS2TGISEdx8xgqpkbytB07XmlQyQdNDrCc1ecSqx0cnmhGvpX+VBwqqSkg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.13.0.tgz", + "integrity": "sha512-7N/+lztJqH4Mrf0lb10R/CbI1EaAMMGyF5y0oJvFoAhafwgiRA7TXyd8TFn8FC8k5y2dTsYogg238qavRGNnlw==", "dev": true, - "dependencies": { - "@typescript-eslint/types": "8.24.0", - "eslint-visitor-keys": "^4.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } + "license": "ISC" }, "node_modules/accessor-fn": { "version": "1.5.1", @@ -1839,9 +1760,9 @@ } }, "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -1876,20 +1797,19 @@ } }, "node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=8" } }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -1903,12 +1823,14 @@ "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "license": "MIT" }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1920,7 +1842,8 @@ "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" }, "node_modules/argparse": { "version": "2.0.1", @@ -1932,6 +1855,7 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", + "license": "MIT", "dependencies": { "tslib": "^2.0.0" }, @@ -1949,13 +1873,13 @@ } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", - "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "dependencies": { - "call-bound": "^1.0.3", - "is-array-buffer": "^3.0.5" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" }, "engines": { "node": ">= 0.4" @@ -1969,6 +1893,7 @@ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -2009,6 +1934,7 @@ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -2025,15 +1951,16 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", - "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -2043,15 +1970,16 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", - "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -2103,15 +2031,6 @@ "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", "dev": true }, - "node_modules/async-function": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", - "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/autoprefixer": { "version": "10.4.20", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", @@ -2153,6 +2072,7 @@ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "license": "MIT", "dependencies": { "possible-typed-array-names": "^1.0.0" }, @@ -2184,7 +2104,8 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" }, "node_modules/base64-arraybuffer": { "version": "1.0.2", @@ -2207,6 +2128,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", "engines": { "node": ">=8" }, @@ -2219,6 +2141,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2228,6 +2151,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -2236,9 +2160,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "funding": [ { "type": "opencollective", @@ -2254,9 +2178,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", - "node-releases": "^2.0.19", + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.1" }, "bin": { @@ -2337,14 +2261,15 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001699", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001699.tgz", - "integrity": "sha512-b+uH5BakXZ9Do9iK+CkDmctUSEqZl+SP056vc5usa0PL+ev5OHw003rZXcnjNDv3L8P5j6rwT6C0BPKSikW08w==", + "version": "1.0.30001680", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001680.tgz", + "integrity": "sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==", "funding": [ { "type": "opencollective", @@ -2381,6 +2306,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2423,6 +2349,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -2446,6 +2373,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -2473,6 +2401,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", "engines": { "node": ">=6" } @@ -2493,6 +2422,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -2503,7 +2433,8 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" }, "node_modules/color-string": { "version": "1.9.1", @@ -2527,6 +2458,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "license": "MIT", "engines": { "node": ">= 6" } @@ -2535,7 +2467,8 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cross-spawn": { "version": "7.0.6", @@ -2562,6 +2495,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "license": "MIT", "bin": { "cssesc": "bin/cssesc" }, @@ -2572,7 +2506,8 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" }, "node_modules/d3": { "version": "7.9.0", @@ -2984,14 +2919,15 @@ "dev": true }, "node_modules/data-view-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", - "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", + "call-bind": "^1.0.6", "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" + "is-data-view": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -3001,29 +2937,31 @@ } }, "node_modules/data-view-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", - "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" + "is-data-view": "^1.0.1" }, "engines": { "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/inspect-js" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/data-view-byte-offset": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", + "call-bind": "^1.0.6", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" }, @@ -3035,12 +2973,13 @@ } }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "ms": "2.1.2" }, "engines": { "node": ">=6.0" @@ -3055,13 +2994,15 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -3079,6 +3020,7 @@ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, + "license": "MIT", "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -3116,12 +3058,14 @@ "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "license": "Apache-2.0" }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "license": "MIT" }, "node_modules/doctrine": { "version": "2.1.0", @@ -3136,12 +3080,12 @@ } }, "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.0.tgz", + "integrity": "sha512-9+Sj30DIu+4KvHqMfLUGLFYL2PkURSYMVXJyXe92nFRvlYq5hBjLEhblKB+vkd/WVlUYMWigiY07T91Fkk0+4A==", "dev": true, "dependencies": { - "call-bind-apply-helpers": "^1.0.1", + "call-bind-apply-helpers": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.2.0" }, @@ -3152,12 +3096,13 @@ "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.97", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.97.tgz", - "integrity": "sha512-HKLtaH02augM7ZOdYRuO19rWDeY+QSJ1VxnXFa/XDFLf07HvM90pALIJFgrO+UVaajI3+aJMMpojoUTLZyQ7JQ==" + "version": "1.5.63", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.63.tgz", + "integrity": "sha512-ddeXKuY9BHo/mw145axlyWjlJ1UBt4WK3AlvkT7W2AbqfRQoacVoRUCF6wL3uIx/8wT9oLKXzI+rFqHHscByaA==" }, "node_modules/embla-carousel": { "version": "8.5.2", @@ -3187,13 +3132,15 @@ "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" }, "node_modules/enhanced-resolve": { - "version": "5.18.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", - "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -3203,28 +3150,27 @@ } }, "node_modules/es-abstract": { - "version": "1.23.9", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", - "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", + "version": "1.23.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.6.tgz", + "integrity": "sha512-Ifco6n3yj2tMZDWNLyloZrytt9lqqlwvS83P3HtaETR0NUOYnIULGGHpktqYGObGy+8wc1okO25p8TjemhImvA==", "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.2", + "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.3", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.1.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.0", - "get-symbol-description": "^1.1.0", + "function.prototype.name": "^1.1.7", + "get-intrinsic": "^1.2.6", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", @@ -3232,33 +3178,31 @@ "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", - "is-shared-array-buffer": "^1.0.4", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", + "is-typed-array": "^1.1.13", "is-weakref": "^1.1.0", - "math-intrinsics": "^1.1.0", + "math-intrinsics": "^1.0.0", "object-inspect": "^1.13.3", "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", + "object.assign": "^4.1.5", "regexp.prototype.flags": "^1.5.3", "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.3", "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.18" + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -3281,42 +3225,43 @@ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/es-iterator-helpers": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", - "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.0.tgz", + "integrity": "sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q==", "dev": true, "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.23.6", + "es-abstract": "^1.23.3", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.6", + "get-intrinsic": "^1.2.4", "globalthis": "^1.0.4", - "gopd": "^1.2.0", + "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "internal-slot": "^1.1.0", - "iterator.prototype": "^1.1.4", - "safe-array-concat": "^1.1.3" + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.3", + "safe-array-concat": "^1.1.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0" }, @@ -3325,30 +3270,28 @@ } }, "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, + "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", + "get-intrinsic": "^1.2.4", "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" + "hasown": "^2.0.1" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", - "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, + "license": "MIT", "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" + "hasown": "^2.0.0" } }, "node_modules/es-to-primitive": { @@ -3381,6 +3324,7 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -3389,21 +3333,22 @@ } }, "node_modules/eslint": { - "version": "9.20.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.20.1.tgz", - "integrity": "sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g==", + "version": "9.22.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.22.0.tgz", + "integrity": "sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.19.0", - "@eslint/core": "^0.11.0", - "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.20.0", - "@eslint/plugin-kit": "^0.2.5", + "@eslint/config-array": "^0.19.2", + "@eslint/config-helpers": "^0.1.0", + "@eslint/core": "^0.12.0", + "@eslint/eslintrc": "^3.3.0", + "@eslint/js": "9.22.0", + "@eslint/plugin-kit": "^0.2.7", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.1", + "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -3411,7 +3356,7 @@ "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.2.0", + "eslint-scope": "^8.3.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", @@ -3448,12 +3393,12 @@ } }, "node_modules/eslint-config-next": { - "version": "15.1.7", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.1.7.tgz", - "integrity": "sha512-zXoMnYUIy3XHaAoOhrcYkT9UQWvXqWju2K7NNsmb5wd/7XESDwof61eUdW4QhERr3eJ9Ko/vnXqIrj8kk/drYw==", + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.2.1.tgz", + "integrity": "sha512-mhsprz7l0no8X+PdDnVHF4dZKu9YBJp2Rf6ztWbXBLJ4h6gxmW//owbbGJMBVUU+PibGJDAqZhW4pt8SC8HSow==", "dev": true, "dependencies": { - "@next/eslint-plugin-next": "15.1.7", + "@next/eslint-plugin-next": "15.2.1", "@rushstack/eslint-patch": "^1.10.3", "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", @@ -3479,6 +3424,7 @@ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", @@ -3490,24 +3436,25 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, "node_modules/eslint-import-resolver-typescript": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.7.0.tgz", - "integrity": "sha512-Vrwyi8HHxY97K5ebydMtffsWAn1SCR9eol49eCd5fJS4O1WV7PaAjbcjmbfJJSMz/t4Mal212Uz/fQZrOB8mow==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", "dev": true, + "license": "ISC", "dependencies": { - "@nolyfill/is-core-module": "1.0.39", - "debug": "^4.3.7", - "enhanced-resolve": "^5.15.0", - "fast-glob": "^3.3.2", - "get-tsconfig": "^4.7.5", - "is-bun-module": "^1.0.2", - "is-glob": "^4.0.3", - "stable-hash": "^0.0.4" + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -3517,44 +3464,7 @@ }, "peerDependencies": { "eslint": "*", - "eslint-plugin-import": "*", - "eslint-plugin-import-x": "*" - }, - "peerDependenciesMeta": { - "eslint-plugin-import": { - "optional": true - }, - "eslint-plugin-import-x": { - "optional": true - } - } - }, - "node_modules/eslint-import-resolver-typescript/node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/eslint-import-resolver-typescript/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" + "eslint-plugin-import": "*" } }, "node_modules/eslint-module-utils": { @@ -3579,6 +3489,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } @@ -3621,6 +3532,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } @@ -3630,6 +3542,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -3664,28 +3577,28 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.37.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz", - "integrity": "sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==", + "version": "7.37.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", + "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", "dev": true, "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.3", + "array.prototype.flatmap": "^1.3.2", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.2.1", + "es-iterator-helpers": "^1.1.0", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.8", "object.fromentries": "^2.0.8", - "object.values": "^1.2.1", + "object.values": "^1.2.0", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.12", + "string.prototype.matchall": "^4.0.11", "string.prototype.repeat": "^1.0.0" }, "engines": { @@ -3696,9 +3609,9 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.1.0.tgz", - "integrity": "sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0.tgz", + "integrity": "sha512-hIOwI+5hYGpJEc4uPRmz2ulCjAGD/N13Lukkh8cLV0i2IRk/bdZDYjgLVHj+U9Z704kLIdIO6iueGvxNur0sgw==", "dev": true, "engines": { "node": ">=10" @@ -3734,9 +3647,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", - "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", + "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -3750,10 +3663,24 @@ } }, "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -3778,11 +3705,24 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/esquery": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -3807,6 +3747,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -3816,6 +3757,7 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -3827,10 +3769,10 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", - "dev": true, + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -3846,7 +3788,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -3864,12 +3806,14 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fastq": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", - "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -3891,6 +3835,7 @@ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^4.0.0" }, @@ -3902,6 +3847,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -3914,6 +3860,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -3930,6 +3877,7 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, + "license": "MIT", "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" @@ -3939,15 +3887,16 @@ } }, "node_modules/flatted": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", - "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", - "dev": true + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true, + "license": "ISC" }, "node_modules/float-tooltip": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/float-tooltip/-/float-tooltip-1.7.3.tgz", - "integrity": "sha512-k7/1nX3J5POXBF+xXt1M33BpBpZgJn+GkFu+u89NuULOZmBCbWywNvS1EmdmADooAMz1MoONMiKvlGZ1kfTrqA==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/float-tooltip/-/float-tooltip-1.7.4.tgz", + "integrity": "sha512-UUcH+5MHMnHf7a3qF2ZJ7J5PTtTKHRqdaoC3VAHZuX8ooEegNWxpmmHk192lABXw0+O+FzGB4anpEiqe6iv+WA==", "dependencies": { "d3-selection": "2 - 3", "kapsule": "^1.16", @@ -3958,24 +3907,19 @@ } }, "node_modules/for-each": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", - "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, + "license": "MIT", "dependencies": { - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "is-callable": "^1.1.3" } }, "node_modules/force-graph": { - "version": "1.49.0", - "resolved": "https://registry.npmjs.org/force-graph/-/force-graph-1.49.0.tgz", - "integrity": "sha512-S8ODRE6eVtHtkIPCRu9Zj03uL/l8EpwKIZnIzLZO6aiZIMQLI8JguEeT3uCozT9kB2nLXem0xCiA7Pnk38Yy7g==", + "version": "1.49.3", + "resolved": "https://registry.npmjs.org/force-graph/-/force-graph-1.49.3.tgz", + "integrity": "sha512-blBqeFq3vdIzqGgvWrML9xA2R0nS5nvjHsEt9lcWVZ29IcdWQ6wa4G0CG/Uv8bP9olwpsJPZSJe3W8vNhiMCnQ==", "dependencies": { "@tweenjs/tween.js": "18 - 25", "accessor-fn": "1", @@ -4001,6 +3945,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -4049,18 +3994,18 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/function.prototype.name": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.7.tgz", + "integrity": "sha512-2g4x+HqTJKM9zcJqBSpjoRmdcPFtJM60J3xJisTQSXBWka5XqyBN/2tNUgma1mztTXyDuUsEtYe5qcs7xYzYQA==", "dev": true, "dependencies": { "call-bind": "^1.0.8", - "call-bound": "^1.0.3", "define-properties": "^1.2.1", "functions-have-names": "^1.2.3", "hasown": "^2.0.2", @@ -4078,26 +4023,27 @@ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-intrinsic": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", - "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", + "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==", "dev": true, "dependencies": { "call-bind-apply-helpers": "^1.0.1", + "dunder-proto": "^1.0.0", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", - "get-proto": "^1.0.0", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" + "math-intrinsics": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -4114,28 +4060,16 @@ "node": ">=6" } }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/get-symbol-description": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", + "call-bind": "^1.0.5", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -4145,10 +4079,11 @@ } }, "node_modules/get-tsconfig": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", - "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.6.tgz", + "integrity": "sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==", "dev": true, + "license": "MIT", "dependencies": { "resolve-pkg-maps": "^1.0.0" }, @@ -4157,20 +4092,23 @@ } }, "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" }, "bin": { "glob": "dist/esm/bin.mjs" }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -4179,6 +4117,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -4190,6 +4129,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -4198,6 +4138,7 @@ "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -4225,6 +4166,7 @@ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, + "license": "MIT", "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" @@ -4252,22 +4194,22 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/has-bigints": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true, - "engines": { - "node": ">= 0.4" - }, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -4277,6 +4219,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -4286,6 +4229,7 @@ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" }, @@ -4325,6 +4269,7 @@ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, + "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" }, @@ -4339,6 +4284,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -4408,10 +4354,11 @@ } }, "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -4437,6 +4384,7 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.19" } @@ -4494,14 +4442,13 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -4516,16 +4463,12 @@ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, "node_modules/is-async-function": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", - "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", "dev": true, "dependencies": { - "async-function": "^1.0.0", - "call-bound": "^1.0.3", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -4553,6 +4496,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -4561,12 +4505,12 @@ } }, "node_modules/is-boolean-object": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", - "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz", + "integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==", "dev": true, "dependencies": { - "call-bound": "^1.0.3", + "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" }, "engines": { @@ -4576,20 +4520,12 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-bun-module": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.3.0.tgz", - "integrity": "sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==", - "dev": true, - "dependencies": { - "semver": "^7.6.3" - } - }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -4598,9 +4534,9 @@ } }, "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "dependencies": { "hasown": "^2.0.2" }, @@ -4657,17 +4593,18 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/is-finalizationregistry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.0.tgz", + "integrity": "sha512-qfMdqbAQEwBw78ZyReKnlA8ezmPdb9BemzIIip/JkjaZUhitfXDkkr+3QTboW0JrSXT1QWyYShpvnNHGZ4c4yA==", "dev": true, "dependencies": { - "call-bound": "^1.0.3" + "call-bind": "^1.0.7" }, "engines": { "node": ">= 0.4" @@ -4680,20 +4617,18 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-generator-function": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", - "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "dev": true, "dependencies": { - "call-bound": "^1.0.3", - "get-proto": "^1.0.0", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -4706,6 +4641,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -4734,10 +4670,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -4789,12 +4739,12 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "dependencies": { - "call-bound": "^1.0.3" + "call-bind": "^1.0.7" }, "engines": { "node": ">= 0.4" @@ -4837,12 +4787,13 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, + "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.16" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -4864,12 +4815,12 @@ } }, "node_modules/is-weakref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", - "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz", + "integrity": "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==", "dev": true, "dependencies": { - "call-bound": "^1.0.3" + "call-bound": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -4879,13 +4830,13 @@ } }, "node_modules/is-weakset": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", "dev": true, "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -4898,24 +4849,26 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" }, "node_modules/iterator.prototype": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", - "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.4.tgz", + "integrity": "sha512-x4WH0BWmrMmg4oHHl+duwubhrvczGlyuGAZu3nvrf0UXOfPu8IhZObFEr7DE/iv01YgVZrsOiRcqw2srkKEDIA==", "dev": true, "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", - "get-proto": "^1.0.0", "has-symbols": "^1.1.0", + "reflect.getprototypeof": "^1.0.8", "set-function-name": "^2.0.2" }, "engines": { @@ -4923,12 +4876,16 @@ } }, "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, + "engines": { + "node": ">=14" + }, "funding": { "url": "https://github.com/sponsors/isaacs" }, @@ -4945,9 +4902,10 @@ } }, "node_modules/jiti": { - "version": "1.21.7", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", - "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "license": "MIT", "bin": { "jiti": "bin/jiti.js" } @@ -4955,7 +4913,8 @@ "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", @@ -4973,7 +4932,8 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -4985,13 +4945,15 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json5": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.0" }, @@ -5004,6 +4966,7 @@ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", "dev": true, + "license": "MIT", "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", @@ -5030,6 +4993,7 @@ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -5057,6 +5021,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -5079,13 +5044,15 @@ "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -5105,12 +5072,14 @@ "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -5134,7 +5103,8 @@ "node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" }, "node_modules/lucide-react": { "version": "0.475.0", @@ -5145,9 +5115,9 @@ } }, "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.0.0.tgz", + "integrity": "sha512-4MqMiKP90ybymYvsut0CH2g4XWbfLtmlCkXmtmdcDCxNB+mQcu1w/1+L/VD7vi/PSv7X2JYV7SCcR+jiPXnQtA==", "dev": true, "engines": { "node": ">= 0.4" @@ -5157,6 +5127,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", "engines": { "node": ">= 8" } @@ -5178,6 +5149,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -5190,6 +5162,7 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5198,20 +5171,23 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true, + "license": "MIT" }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "license": "MIT", "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", @@ -5219,15 +5195,16 @@ } }, "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -5239,14 +5216,15 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/next": { - "version": "15.1.7", - "resolved": "https://registry.npmjs.org/next/-/next-15.1.7.tgz", - "integrity": "sha512-GNeINPGS9c6OZKCvKypbL8GTsT5GhWPp4DM0fzkXJuXMilOO2EeFxuAY6JZbtk6XIl6Ws10ag3xRINDjSO5+wg==", + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/next/-/next-15.2.1.tgz", + "integrity": "sha512-zxbsdQv3OqWXybK5tMkPCBKyhIz63RstJ+NvlfkaLMc/m5MwXgz2e92k+hSKcyBpyADhMk2C31RIiaDjUZae7g==", "dependencies": { - "@next/env": "15.1.7", + "@next/env": "15.2.1", "@swc/counter": "0.1.3", "@swc/helpers": "0.5.15", "busboy": "1.6.0", @@ -5261,14 +5239,14 @@ "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "15.1.7", - "@next/swc-darwin-x64": "15.1.7", - "@next/swc-linux-arm64-gnu": "15.1.7", - "@next/swc-linux-arm64-musl": "15.1.7", - "@next/swc-linux-x64-gnu": "15.1.7", - "@next/swc-linux-x64-musl": "15.1.7", - "@next/swc-win32-arm64-msvc": "15.1.7", - "@next/swc-win32-x64-msvc": "15.1.7", + "@next/swc-darwin-arm64": "15.2.1", + "@next/swc-darwin-x64": "15.2.1", + "@next/swc-linux-arm64-gnu": "15.2.1", + "@next/swc-linux-arm64-musl": "15.2.1", + "@next/swc-linux-x64-gnu": "15.2.1", + "@next/swc-linux-x64-musl": "15.2.1", + "@next/swc-win32-arm64-msvc": "15.2.1", + "@next/swc-win32-x64-msvc": "15.2.1", "sharp": "^0.33.5" }, "peerDependencies": { @@ -5322,14 +5300,15 @@ } }, "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==" + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5346,6 +5325,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5354,14 +5334,15 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", "dev": true, "engines": { "node": ">= 0.4" @@ -5375,21 +5356,21 @@ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/object.assign": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", + "call-bind": "^1.0.5", "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0", - "has-symbols": "^1.1.0", + "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, "engines": { @@ -5418,6 +5399,7 @@ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -5436,6 +5418,7 @@ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -5446,13 +5429,13 @@ } }, "node_modules/object.values": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", - "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, @@ -5468,6 +5451,7 @@ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -5480,28 +5464,12 @@ "node": ">= 0.8.0" } }, - "node_modules/own-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", - "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.6", - "object-keys": "^1.1.1", - "safe-push-apply": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -5517,6 +5485,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -5527,11 +5496,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -5566,6 +5530,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -5574,6 +5539,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", "engines": { "node": ">=8" } @@ -5581,12 +5547,14 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" }, "node_modules/path-scurry": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -5607,6 +5575,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -5614,28 +5583,21 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/pirates": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/playwright": { - "version": "1.50.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.50.1.tgz", - "integrity": "sha512-G8rwsOQJ63XG6BbKj2w5rHeavFjy5zynBA9zsJMMtBoe/Uf757oG12NXz6e6OirF7RCrTVAKFXbLmn1RbL7Qaw==", + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.51.0.tgz", + "integrity": "sha512-442pTfGM0xxfCYxuBa/Pu6B2OqxqqaYq39JS8QDMGThUvIOCd6s0ANDog3uwA0cHavVlnTQzGCN7Id2YekDSXA==", "dependencies": { - "playwright-core": "1.50.1" + "playwright-core": "1.51.0" }, "bin": { "playwright": "cli.js" @@ -5648,9 +5610,9 @@ } }, "node_modules/playwright-core": { - "version": "1.50.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.50.1.tgz", - "integrity": "sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ==", + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.51.0.tgz", + "integrity": "sha512-x47yPE3Zwhlil7wlNU/iktF7t2r/URR3VLbH6EknJd/04Qc/PSJ0EY3CMXipmglLG+zyRxW6HNo2EGbKLHPWMg==", "bin": { "playwright-core": "cli.js" }, @@ -5659,18 +5621,19 @@ } }, "node_modules/possible-typed-array-names": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", - "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/postcss": { - "version": "8.5.2", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz", - "integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==", + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", "funding": [ { "type": "opencollective", @@ -5686,7 +5649,7 @@ } ], "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.7", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -5698,6 +5661,7 @@ "version": "15.1.0", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", @@ -5714,6 +5678,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "license": "MIT", "dependencies": { "camelcase-css": "^2.0.1" }, @@ -5742,6 +5707,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "lilconfig": "^3.0.0", "yaml": "^2.3.4" @@ -5776,6 +5742,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "postcss-selector-parser": "^6.1.1" }, @@ -5801,12 +5768,13 @@ "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT" }, "node_modules/preact": { - "version": "10.25.4", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.25.4.tgz", - "integrity": "sha512-jLdZDb+Q+odkHJ+MpW/9U5cODzqnB+fy2EiHSZES7ldV5LK7yjlVzTp7R8Xy6W6y75kfK8iWYtFVH7lvjwrCMA==", + "version": "10.26.4", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.26.4.tgz", + "integrity": "sha512-KJhO7LBFTjP71d83trW+Ilnjbo+ySsaAgCfXOXUlmGzJ4ygYPWmysm77yg4emwfmoz3b22yvH5IsVFHbhUaH5w==", "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -5817,6 +5785,7 @@ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } @@ -5833,6 +5802,7 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -5877,12 +5847,14 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" }, @@ -5905,6 +5877,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -5937,7 +5910,8 @@ "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" }, "node_modules/react-json-tree": { "version": "0.19.0", @@ -6071,14 +6045,25 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "license": "MIT", "dependencies": { "pify": "^2.3.0" } }, + "node_modules/read-cache/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -6087,19 +6072,19 @@ } }, "node_modules/reflect.getprototypeof": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", - "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.8.tgz", + "integrity": "sha512-B5dj6usc5dkk8uFliwjwDHM8To5/QwdKz9JcBZ8Ic4G1f0YmeeJTtE/ZTdgRFPAfxZFiUaPhZ1Jcs4qeagItGQ==", "dev": true, "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", + "dunder-proto": "^1.0.0", + "es-abstract": "^1.23.5", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.1", - "which-builtin-type": "^1.2.1" + "get-intrinsic": "^1.2.4", + "gopd": "^1.2.0", + "which-builtin-type": "^1.2.0" }, "engines": { "node": ">= 0.4" @@ -6136,16 +6121,14 @@ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "node_modules/regexp.prototype.flags": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", - "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", + "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.8", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-errors": "^1.3.0", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", "set-function-name": "^2.0.2" }, "engines": { @@ -6156,20 +6139,18 @@ } }, "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "license": "MIT", "dependencies": { - "is-core-module": "^2.16.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, - "engines": { - "node": ">= 0.4" - }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -6188,6 +6169,7 @@ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } @@ -6196,6 +6178,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -6224,6 +6207,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -6252,22 +6236,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safe-push-apply": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", - "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/safe-regex-test": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", @@ -6294,14 +6262,15 @@ "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" } }, "node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "devOptional": true, "bin": { "semver": "bin/semver.js" @@ -6315,6 +6284,7 @@ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, + "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -6332,6 +6302,7 @@ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, + "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -6342,20 +6313,6 @@ "node": ">= 0.4" } }, - "node_modules/set-proto": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", - "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", - "dev": true, - "dependencies": { - "dunder-proto": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/sharp": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", @@ -6399,6 +6356,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -6410,6 +6368,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", "engines": { "node": ">=8" } @@ -6490,6 +6449,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", "engines": { "node": ">=14" }, @@ -6522,12 +6482,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/stable-hash": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz", - "integrity": "sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==", - "dev": true - }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -6540,6 +6494,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -6557,6 +6512,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -6566,28 +6522,37 @@ "node": ">=8" } }, - "node_modules/string-width-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, "node_modules/string-width-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { + "node_modules/string-width/node_modules/ansi-regex": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/string.prototype.includes": { @@ -6605,24 +6570,23 @@ } }, "node_modules/string.prototype.matchall": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", - "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", "dev": true, "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.23.6", + "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.6", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "internal-slot": "^1.1.0", - "regexp.prototype.flags": "^1.5.3", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", "set-function-name": "^2.0.2", - "side-channel": "^1.1.0" + "side-channel": "^1.0.6" }, "engines": { "node": ">= 0.4" @@ -6685,6 +6649,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -6698,17 +6663,15 @@ } }, "node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=8" } }, "node_modules/strip-ansi-cjs": { @@ -6716,6 +6679,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -6723,19 +6687,12 @@ "node": ">=8" } }, - "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -6778,6 +6735,7 @@ "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", @@ -6800,6 +6758,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -6811,6 +6770,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -6867,41 +6827,17 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", + "license": "MIT", "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } }, - "node_modules/tailwindcss/node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/tailwindcss/node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -6918,6 +6854,7 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "license": "MIT", "dependencies": { "any-promise": "^1.0.0" } @@ -6926,6 +6863,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "license": "MIT", "dependencies": { "thenify": ">= 3.1.0 < 4" }, @@ -6942,6 +6880,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -6950,27 +6889,30 @@ } }, "node_modules/ts-api-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", - "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=18.12" + "node": ">=16" }, "peerDependencies": { - "typescript": ">=4.8.4" + "typescript": ">=4.2.0" } }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "license": "Apache-2.0" }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, + "license": "MIT", "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", @@ -6988,6 +6930,7 @@ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -6996,30 +6939,32 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -7029,18 +6974,18 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.3.tgz", + "integrity": "sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw==", "dev": true, "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "reflect.getprototypeof": "^1.0.6" }, "engines": { "node": ">= 0.4" @@ -7070,9 +7015,9 @@ } }, "node_modules/typescript": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", + "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -7083,18 +7028,16 @@ } }, "node_modules/unbox-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", + "call-bind": "^1.0.2", "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7107,9 +7050,9 @@ "dev": true }, "node_modules/update-browserslist-db": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", - "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "funding": [ { "type": "opencollective", @@ -7126,7 +7069,7 @@ ], "dependencies": { "escalade": "^3.2.0", - "picocolors": "^1.1.1" + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -7188,7 +7131,8 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" }, "node_modules/utrie": { "version": "1.0.2", @@ -7214,6 +7158,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -7289,16 +7234,15 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", - "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.16.tgz", + "integrity": "sha512-g+N+GAWiRj66DngFwHvISJd+ITsyphZvD1vChfVg6cEdnzy53GzB3oy0fUNlvhz7H7+MiqhYr26qxQShCpKTTQ==", "dev": true, "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "gopd": "^1.2.0", + "gopd": "^1.0.1", "has-tostringtag": "^1.0.2" }, "engines": { @@ -7313,6 +7257,7 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -7321,6 +7266,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -7338,6 +7284,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -7350,23 +7297,17 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" }, "node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -7376,21 +7317,23 @@ "node": ">=8" } }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "node_modules/wrap-ansi/node_modules/ansi-regex": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -7398,6 +7341,21 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -7407,9 +7365,10 @@ } }, "node_modules/yaml": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", - "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", + "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", + "license": "ISC", "bin": { "yaml": "bin.mjs" }, @@ -7422,6 +7381,7 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, From 83b8cba934e31408625f76201b88f25fc529f9fe Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Tue, 11 Mar 2025 12:31:01 +0200 Subject: [PATCH 100/189] adjust tests for mobile responsiveness --- app/components/toolbar.tsx | 1 + app/page.tsx | 4 +- e2e/config/constants.ts | 7 +- e2e/logic/POM/codeGraph.ts | 171 ++++++++++++++++------------- e2e/logic/utils.ts | 23 ++-- e2e/tests/canvas.spec.ts | 45 ++++---- e2e/tests/chat.spec.ts | 32 +++--- e2e/tests/navBar.spec.ts | 2 +- e2e/tests/nodeDetailsPanel.spec.ts | 16 +-- e2e/tests/searchBar.spec.ts | 16 +-- 10 files changed, 168 insertions(+), 149 deletions(-) diff --git a/app/components/toolbar.tsx b/app/components/toolbar.tsx index 35fd7b46..9769f25e 100644 --- a/app/components/toolbar.tsx +++ b/app/components/toolbar.tsx @@ -49,6 +49,7 @@ export function Toolbar({ chartRef, className, handleDownloadImage }: Props) {
- avoidOverlap(data.nodes as Position[])} - nodeVisibility="visible" - linkVisibility="visible" - linkCurvature="curve" - linkDirectionalArrowRelPos={1} - linkDirectionalArrowColor={(link) => (link.isPath || link.isPathSelected) ? PATH_COLOR : link.color} - linkDirectionalArrowLength={(link) => link.source.id === link.target.id ? 0 : (link.id === selectedObj?.id || link.isPathSelected) ? 3 : 2} - nodeRelSize={NODE_SIZE} - linkLineDash={(link) => (link.isPath && !link.isPathSelected) ? [5, 5] : []} - linkColor={(link) => (link.isPath || link.isPathSelected) ? PATH_COLOR : link.color} - linkWidth={(link) => (link.id === selectedObj?.id || link.isPathSelected) ? 2 : 1} - nodeCanvasObjectMode={() => 'after'} - linkCanvasObjectMode={() => 'after'} - nodeCanvasObject={(node, ctx) => { - if (!node.x || !node.y) return - - if (isPathResponse) { - if (node.isPathSelected) { - ctx.fillStyle = node.color; - ctx.strokeStyle = PATH_COLOR; - ctx.lineWidth = 1 - } else if (node.isPath) { - ctx.fillStyle = node.color; - ctx.strokeStyle = PATH_COLOR; - ctx.lineWidth = 0.5 - } else { - ctx.fillStyle = '#E5E5E5'; - ctx.strokeStyle = 'gray'; - ctx.lineWidth = 0.5 - } - } else if (isPathResponse === undefined) { - if (node.isPathSelected) { - ctx.fillStyle = node.color; - ctx.strokeStyle = PATH_COLOR; - ctx.lineWidth = 1 - } else if (node.isPath) { - ctx.fillStyle = node.color; - ctx.strokeStyle = PATH_COLOR; - ctx.lineWidth = 0.5 - } else { - ctx.fillStyle = node.color; - ctx.strokeStyle = 'black'; - ctx.lineWidth = selectedObjects.some(obj => obj.id === node.id) || selectedObj?.id === node.id ? 1 : 0.5 - } - } else { - ctx.fillStyle = node.color; - ctx.strokeStyle = 'black'; - ctx.lineWidth = selectedObjects.some(obj => obj.id === node.id) || selectedObj?.id === node.id ? 1 : 0.5 - } - - ctx.beginPath(); - ctx.arc(node.x, node.y, NODE_SIZE, 0, 2 * Math.PI, false); - ctx.stroke(); - ctx.fill(); - - ctx.fillStyle = 'black'; - ctx.textAlign = 'center'; - ctx.textBaseline = 'middle'; - ctx.font = '2px Arial'; - const textWidth = ctx.measureText(node.name).width; - const ellipsis = '...'; - const ellipsisWidth = ctx.measureText(ellipsis).width; - const nodeSize = NODE_SIZE * 2 - PADDING; - let { name } = { ...node } - - // truncate text if it's too long - if (textWidth > nodeSize) { - while (name.length > 0 && ctx.measureText(name).width + ellipsisWidth > nodeSize) { - name = name.slice(0, -1); - } - name += ellipsis; - } - - // add label - ctx.fillText(name, node.x, node.y); - }} - linkCanvasObject={(link, ctx) => { - const start = link.source; - const end = link.target; - - if (!start.x || !start.y || !end.x || !end.y) return - - let textX, textY, angle; - - if (start.id === end.id) { - const radius = NODE_SIZE * link.curve * 6.2; - const angleOffset = -Math.PI / 4; // 45 degrees offset for text alignment - textX = start.x + radius * Math.cos(angleOffset); - textY = start.y + radius * Math.sin(angleOffset); - angle = -angleOffset; - } else { - const midX = (start.x + end.x) / 2; - const midY = (start.y + end.y) / 2; - const offset = link.curve / 2; - - angle = Math.atan2(end.y - start.y, end.x - start.x); - - // maintain label vertical orientation for legibility - if (angle > Math.PI / 2) angle = -(Math.PI - angle); - if (angle < -Math.PI / 2) angle = -(-Math.PI - angle); - - // Calculate perpendicular offset - const perpX = -Math.sin(angle) * offset; - const perpY = Math.cos(angle) * offset; - - // Adjust position to compensate for rotation around origin - const cos = Math.cos(angle); - const sin = Math.sin(angle); - textX = midX + perpX; - textY = midY + perpY; - const rotatedX = textX * cos + textY * sin; - const rotatedY = -textX * sin + textY * cos; - textX = rotatedX; - textY = rotatedY; - } - - // Setup text properties to measure background size - ctx.font = '2px Arial'; - const padding = 0.5; - // Get text width and height - const label = graph.LabelsMap.get(link.label)! - let { textWidth, textHeight } = label - - if (!textWidth || !textHeight) { - const { width, actualBoundingBoxAscent, actualBoundingBoxDescent } = ctx.measureText(link.label) - textWidth = width - textHeight = actualBoundingBoxAscent + actualBoundingBoxDescent - graph.LabelsMap.set(link.label, { ...label, textWidth, textHeight }) - } - - // Save the current context state - ctx.save(); - - // add label with background and rotation - ctx.rotate(angle); - - // Draw background - ctx.fillStyle = 'white'; - ctx.fillRect( - textX - textWidth / 2 - padding, - textY - textHeight / 2 - padding, - textWidth + padding * 2, - textHeight + padding * 2 - ); - - // Draw text - ctx.globalAlpha = 1; - ctx.fillStyle = 'black'; - ctx.textAlign = 'center'; - ctx.textBaseline = 'middle'; - ctx.fillText(link.label, textX, textY); - - ctx.restore(); // reset rotation - }} - onNodeClick={screenSize > Number(process.env.NEXT_PUBLIC_MOBILE_BREAKPOINT) || isShowPath ? handleNodeClick : handleRightClick} + Number(process.env.NEXT_PUBLIC_MOBILE_BREAKPOINT) || isShowPath ? (node: Node, _evt: MouseEvent) => handleNodeClick(node) : (node: Node, evt: MouseEvent) => handleRightClick(node, evt)} onNodeRightClick={handleRightClick} - onNodeDragEnd={(n, translate) => setPosition(prev => { - return prev && { x: prev.x + translate.x * (chartRef.current?.zoom() ?? 1), y: prev.y + translate.y * (chartRef.current?.zoom() ?? 1) } - })} onLinkClick={screenSize > Number(process.env.NEXT_PUBLIC_MOBILE_BREAKPOINT) && isPathResponse ? handleLinkClick : handleRightClick} onLinkRightClick={handleRightClick} - onBackgroundRightClick={unsetSelectedObjects} onBackgroundClick={unsetSelectedObjects} + onBackgroundRightClick={unsetSelectedObjects} onZoom={() => unsetSelectedObjects()} - onEngineStop={() => { - setCooldownTicks(0) - debugger - handleZoomToFit(chartRef, zoomedNodes.length === 1 ? 4 : 1, (n: NodeObject) => zoomedNodes.some(node => node.id === n.id)) - setZoomedNodes([]) - }} + onEngineStop={handleEngineStop} cooldownTicks={cooldownTicks} - cooldownTime={6000} />
) diff --git a/app/components/model.ts b/app/components/model.ts index 130e60a7..415877bd 100644 --- a/app/components/model.ts +++ b/app/components/model.ts @@ -1,4 +1,3 @@ -import { LinkObject, NodeObject } from 'react-force-graph-2d' import { Path } from '@/lib/utils' export interface GraphData { @@ -13,34 +12,37 @@ export interface Category { export interface Label { name: string, - textWidth: number, - textHeight: number, } -export type Node = NodeObject<{ +export interface Node { id: number, name: string, category: string, color: string, + visible: boolean, collapsed: boolean, expand: boolean, - visible: boolean, isPathSelected: boolean, isPath: boolean, + x?: number, + y?: number, + vx?: number, + vy?: number, [key: string]: any, -}> +} -export type Link = LinkObject +} const COLORS_ORDER_NAME = [ "blue", @@ -226,18 +228,19 @@ export class Graph { let label = this.labelsMap.get(edgeData.relation) if (!label) { - label = { name: edgeData.relation, textWidth: 0, textHeight: 0 } + label = { name: edgeData.relation } this.labelsMap.set(edgeData.relation, label) this.labels.push(label) } link = { id: edgeData.id, - source, - target, + source: edgeData.src_node, + target: edgeData.dest_node, label: edgeData.relation, visible: true, expand: false, + color: "#999999", collapsed, isPathSelected: false, isPath: !!path, @@ -251,12 +254,12 @@ export class Graph { newElements.links.forEach(link => { const start = link.source const end = link.target - const sameNodesLinks = this.Elements.links.filter(l => (l.source.id === start.id && l.target.id === end.id) || (l.target.id === start.id && l.source.id === end.id)) + const sameNodesLinks = this.elements.links.filter(l => (l.source === start && l.target === end) || (l.target === start && l.source === end)) const index = sameNodesLinks.findIndex(l => l.id === link.id) ?? 0 const even = index % 2 === 0 let curve - if (start.id === end.id) { + if (start === end) { if (even) { curve = Math.floor(-(index / 2)) - 3 } else { @@ -282,7 +285,7 @@ export class Graph { this.elements = { nodes: this.elements.nodes, links: this.elements.links.map(link => { - if (this.elements.nodes.map(n => n.id).includes(link.source.id) && this.elements.nodes.map(n => n.id).includes(link.target.id)) { + if (this.elements.nodes.map(n => n.id).includes(link.source) && this.elements.nodes.map(n => n.id).includes(link.target)) { return link } this.linksMap.delete(link.id) @@ -291,15 +294,15 @@ export class Graph { } public visibleLinks(visible: boolean, ids?: number[]) { - const elements = ids ? this.elements.links.filter(link => ids.includes(link.source.id) || ids.includes(link.target.id)) : this.elements.links + const elements = ids ? this.elements.links.filter(link => ids.includes(link.source) || ids.includes(link.target)) : this.elements.links elements.forEach(link => { - if (visible && this.elements.nodes.map(n => n.id).includes(link.source.id) && link.source.visible && this.elements.nodes.map(n => n.id).includes(link.target.id) && link.target.visible) { + if (visible && this.elements.nodes.find(n => n.id === link.source)?.visible && this.elements.nodes.find(n => n.id === link.target)?.visible) { // eslint-disable-next-line no-param-reassign link.visible = true } - if (!visible && ((this.elements.nodes.map(n => n.id).includes(link.source.id) && !link.source.visible) || (this.elements.nodes.map(n => n.id).includes(link.target.id) && !link.target.visible))) { + if (!visible && (this.elements.nodes.find(n => n.id === link.source)?.visible === false || this.elements.nodes.find(n => n.id === link.target)?.visible === false)) { // eslint-disable-next-line no-param-reassign link.visible = false } diff --git a/app/page.tsx b/app/page.tsx index c78b4901..9d4144a9 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,8 +1,8 @@ 'use client' -import { MutableRefObject, useEffect, useRef, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { Chat } from './components/chat'; -import { Graph, GraphData, Link as LinkType, Node } from './components/model'; +import { Graph, GraphData, Node } from './components/model'; import { AlignRight, BookOpen, BoomBox, Download, Github, HomeIcon, Search, X } from 'lucide-react'; import Link from 'next/link'; import { ImperativePanelHandle, Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels"; @@ -17,10 +17,9 @@ import { Progress } from '@/components/ui/progress'; import { Carousel, CarouselApi, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from '@/components/ui/carousel'; import { Drawer, DrawerContent, DrawerDescription, DrawerTitle, DrawerTrigger } from '@/components/ui/drawer'; import Input from './components/Input'; -import { ForceGraphMethods, NodeObject } from 'react-force-graph-2d'; import { Labels } from './components/labels'; import { Toolbar } from './components/toolbar'; -import { cn, handleZoomToFit, Message, Path, PathData, PathNode } from '@/lib/utils'; +import { cn, GraphRef, handleZoomToFit, Message, Path, PathData, PathNode } from '@/lib/utils'; import { GraphContext } from './components/provider'; type Tip = { @@ -67,8 +66,8 @@ export default function Home() { const [options, setOptions] = useState([]); const [path, setPath] = useState(); const [isSubmit, setIsSubmit] = useState(false); - const desktopChartRef = useRef>() - const mobileChartRef = useRef>() + const desktopChartRef = useRef() + const mobileChartRef = useRef() const [menuOpen, setMenuOpen] = useState(false) const [chatOpen, setChatOpen] = useState(false) const [searchNode, setSearchNode] = useState({}); @@ -190,7 +189,7 @@ export default function Home() { return graph.extend(json.result.neighbors, true) } - const handleSearchSubmit = (node: any, chartRef: MutableRefObject | undefined>) => { + const handleSearchSubmit = (node: any, chartRef: GraphRef) => { const chart = chartRef.current if (chart) { @@ -211,7 +210,7 @@ export default function Home() { } setTimeout(() => { - handleZoomToFit(chartRef, 4, (n: NodeObject) => n.id === chartNode!.id) + handleZoomToFit(chartRef, 4, (n: GraphNode) => n.id === chartNode!.id) }, 0) setSearchNode(chartNode) setOptionsOpen(false) diff --git a/lib/utils.ts b/lib/utils.ts index 2946411b..2dcb8c2d 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -2,7 +2,6 @@ import { Link, Node } from "@/app/components/model" import { type ClassValue, clsx } from "clsx" import { MutableRefObject } from "react" import { twMerge } from "tailwind-merge" -import { ForceGraphMethods, NodeObject } from "react-force-graph-2d" export type PathData = { nodes: any[] @@ -35,13 +34,13 @@ export interface Message { graphName?: string; } -export type GraphRef = MutableRefObject | undefined> +export type GraphRef = MutableRefObject export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } -export function handleZoomToFit(chartRef: GraphRef, paddingMultiplier = 1, filter?: (node: NodeObject) => boolean) { +export function handleZoomToFit(chartRef: GraphRef, paddingMultiplier = 1, filter?: (node: NodeGraph) => boolean) { const chart = chartRef.current if (chart) { // Find the currently visible canvas by checking display property diff --git a/package-lock.json b/package-lock.json index 1eeadbdb..bb1f5672 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "code-graph", "version": "0.2.0", "dependencies": { + "@falkordb/canvas": "^0.0.6", "@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dropdown-menu": "^2.1.6", @@ -30,7 +31,6 @@ "playwright": "^1.49.1", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-force-graph-2d": "^1.27.0", "react-gtm-module": "^2.0.11", "react-json-tree": "^0.19.0", "react-resizable-panels": "^2.1.7", @@ -216,6 +216,26 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@falkordb/canvas": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@falkordb/canvas/-/canvas-0.0.6.tgz", + "integrity": "sha512-5r2dEt3O05dz5drfzHUxEShjqAi1kkDMUadvgBV3rq2YOlZmU9vAOYneU0mpAU1UJOprc+yc78xjTEGMict3Vw==", + "license": "MIT", + "dependencies": { + "d3": "^7.9.0", + "force-graph": "^1.44.4", + "react": "^19.2.3" + } + }, + "node_modules/@falkordb/canvas/node_modules/react": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", + "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@floating-ui/core": { "version": "1.6.9", "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz", @@ -874,9 +894,9 @@ } }, "node_modules/@next/env": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.7.tgz", - "integrity": "sha512-4h6Y2NyEkIEN7Z8YxkA27pq6zTkS09bUSYC0xjd0NpwFxjnIKeZEeH591o5WECSmjpUhLn3H2QLJcDye3Uzcvg==", + "version": "15.5.9", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.9.tgz", + "integrity": "sha512-4GlTZ+EJM7WaW2HEZcyU317tIQDjkQIyENDLxYJfSWlfqguN+dHkZgyQTV/7ykvobU7yEH5gKvreNrH4B6QgIg==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { @@ -1895,7 +1915,8 @@ "node_modules/@tweenjs/tween.js": { "version": "25.0.0", "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-25.0.0.tgz", - "integrity": "sha512-XKLA6syeBUaPzx4j3qwMqzzq+V4uo72BnlbOjmuljLrRqdsd3qnzvZZoxvMHZ23ndsRS4aufU6JOZYpCbU6T1A==" + "integrity": "sha512-XKLA6syeBUaPzx4j3qwMqzzq+V4uo72BnlbOjmuljLrRqdsd3qnzvZZoxvMHZ23ndsRS4aufU6JOZYpCbU6T1A==", + "license": "MIT" }, "node_modules/@types/estree": { "version": "1.0.6", @@ -2181,9 +2202,10 @@ "license": "ISC" }, "node_modules/accessor-fn": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/accessor-fn/-/accessor-fn-1.5.1.tgz", - "integrity": "sha512-zZpFYBqIL1Aqg+f2qmYHJ8+yIZF7/tP6PUGx2/QM0uGPSO5UegpinmkNwDohxWtOj586BpMPVRUjce2HI6xB3A==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/accessor-fn/-/accessor-fn-1.5.3.tgz", + "integrity": "sha512-rkAofCwe/FvYFUlMB0v0gWmhqtfAtV1IUkdPbfhTUyYniu5LrC0A0UJkTH0Jv3S8SvwkmfuAlY+mQIJATdocMA==", + "license": "MIT", "engines": { "node": ">=12" } @@ -2562,6 +2584,7 @@ "version": "6.1.4", "resolved": "https://registry.npmjs.org/bezier-js/-/bezier-js-6.1.4.tgz", "integrity": "sha512-PA0FW9ZpcHbojUCMu28z9Vg/fNkwTj5YhusSAjHHDfHDGLxJ6YUKrAN2vk1fP2MMOxVw4Oko16FMlRGVBGqLKg==", + "license": "MIT", "funding": { "type": "individual", "url": "https://github.com/Pomax/bezierjs/blob/master/FUNDING.md" @@ -2722,9 +2745,10 @@ "license": "CC-BY-4.0" }, "node_modules/canvas-color-tracker": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/canvas-color-tracker/-/canvas-color-tracker-1.3.1.tgz", - "integrity": "sha512-eNycxGS7oQ3IS/9QQY41f/aQjiO9Y/MtedhCgSdsbLSxC9EyUD8L3ehl/Q3Kfmvt8um79S45PBV+5Rxm5ztdSw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/canvas-color-tracker/-/canvas-color-tracker-1.3.2.tgz", + "integrity": "sha512-ryQkDX26yJ3CXzb3hxUVNlg1NKE4REc5crLBq661Nxzr8TNd236SaEf2ffYLXyI5tSABSeguHLqcVq4vf9L3Zg==", + "license": "MIT", "dependencies": { "tinycolor2": "^1.6.0" }, @@ -2940,9 +2964,9 @@ } }, "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "license": "MIT" }, "node_modules/d3": { @@ -3007,7 +3031,8 @@ "node_modules/d3-binarytree": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/d3-binarytree/-/d3-binarytree-1.0.2.tgz", - "integrity": "sha512-cElUNH+sHu95L04m92pG73t2MEJXKu+GeKUN1TJkFsu93E5W8E9Sc3kHEGJKgenGvj19m6upSn2EunvMgMD2Yw==" + "integrity": "sha512-cElUNH+sHu95L04m92pG73t2MEJXKu+GeKUN1TJkFsu93E5W8E9Sc3kHEGJKgenGvj19m6upSn2EunvMgMD2Yw==", + "license": "MIT" }, "node_modules/d3-brush": { "version": "3.0.0", @@ -3150,9 +3175,10 @@ } }, "node_modules/d3-force-3d": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/d3-force-3d/-/d3-force-3d-3.0.5.tgz", - "integrity": "sha512-tdwhAhoTYZY/a6eo9nR7HP3xSW/C6XvJTbeRpR92nlPzH6OiE+4MliN9feuSFd0tPtEUo+191qOhCTWx3NYifg==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/d3-force-3d/-/d3-force-3d-3.0.6.tgz", + "integrity": "sha512-4tsKHUPLOVkyfEffZo1v6sFHvGFwAIIjt/W8IThbp08DYAsXZck+2pSHEG5W1+gQgEvFLdZkYvmJAbRM2EzMnA==", + "license": "MIT", "dependencies": { "d3-binarytree": "1", "d3-dispatch": "1 - 3", @@ -3205,7 +3231,8 @@ "node_modules/d3-octree": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/d3-octree/-/d3-octree-1.1.0.tgz", - "integrity": "sha512-F8gPlqpP+HwRPMO/8uOu5wjH110+6q4cgJvgJT6vlpy3BEaDIKlTZrgHKZSp/i1InRpVfh4puY/kvL6MxK930A==" + "integrity": "sha512-F8gPlqpP+HwRPMO/8uOu5wjH110+6q4cgJvgJT6vlpy3BEaDIKlTZrgHKZSp/i1InRpVfh4puY/kvL6MxK930A==", + "license": "MIT" }, "node_modules/d3-path": { "version": "3.1.0", @@ -4340,9 +4367,10 @@ "license": "ISC" }, "node_modules/float-tooltip": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/float-tooltip/-/float-tooltip-1.7.4.tgz", - "integrity": "sha512-UUcH+5MHMnHf7a3qF2ZJ7J5PTtTKHRqdaoC3VAHZuX8ooEegNWxpmmHk192lABXw0+O+FzGB4anpEiqe6iv+WA==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/float-tooltip/-/float-tooltip-1.7.5.tgz", + "integrity": "sha512-/kXzuDnnBqyyWyhDMH7+PfP8J/oXiAavGzcRxASOMRHFuReDtofizLLJsf7nnDLAfEaMW4pVWaXrAjtnglpEkg==", + "license": "MIT", "dependencies": { "d3-selection": "2 - 3", "kapsule": "^1.16", @@ -4363,9 +4391,10 @@ } }, "node_modules/force-graph": { - "version": "1.49.3", - "resolved": "https://registry.npmjs.org/force-graph/-/force-graph-1.49.3.tgz", - "integrity": "sha512-blBqeFq3vdIzqGgvWrML9xA2R0nS5nvjHsEt9lcWVZ29IcdWQ6wa4G0CG/Uv8bP9olwpsJPZSJe3W8vNhiMCnQ==", + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/force-graph/-/force-graph-1.51.0.tgz", + "integrity": "sha512-aTnihCmiMA0ItLJLCbrQYS9mzriopW24goFPgUnKAAmAlPogTSmFWqoBPMXzIfPb7bs04Hur5zEI4WYgLW3Sig==", + "license": "MIT", "dependencies": { "@tweenjs/tween.js": "18 - 25", "accessor-fn": "1", @@ -4378,7 +4407,7 @@ "d3-scale-chromatic": "1 - 3", "d3-selection": "2 - 3", "d3-zoom": "2 - 3", - "float-tooltip": "^1.6", + "float-tooltip": "^1.7", "index-array-by": "1", "kapsule": "^1.16", "lodash-es": "4" @@ -4843,6 +4872,7 @@ "version": "1.4.2", "resolved": "https://registry.npmjs.org/index-array-by/-/index-array-by-1.4.2.tgz", "integrity": "sha512-SP23P27OUKzXWEC/TOyWlwLviofQkCSCKONnc62eItjp69yCZZPqDQtr3Pw5gJDnPeUMqExmKydNZaJO0FU9pw==", + "license": "MIT", "engines": { "node": ">=12" } @@ -5343,14 +5373,6 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/jerrypick": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/jerrypick/-/jerrypick-1.1.1.tgz", - "integrity": "sha512-XTtedPYEyVp4t6hJrXuRKr/jHj8SC4z+4K0b396PMkov6muL+i8IIamJIvZWe3jUspgIJak0P+BaWKawMYNBLg==", - "engines": { - "node": ">=12" - } - }, "node_modules/jiti": { "version": "1.21.6", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", @@ -5430,9 +5452,10 @@ } }, "node_modules/kapsule": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/kapsule/-/kapsule-1.16.0.tgz", - "integrity": "sha512-4f/z/Luu0cEXmagCwaFyzvfZai2HKgB4CQLwmsMUA+jlUbW94HfFSX+TWZxzWoMSO6b6aR+FD2Xd5z88VYZJTw==", + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/kapsule/-/kapsule-1.16.3.tgz", + "integrity": "sha512-4+5mNNf4vZDSwPhKprKwz3330iisPrb08JyMgbsdFrimBCKNHecua/WBwvVg3n7vwx0C1ARjfhwIpbrbd9n5wg==", + "license": "MIT", "dependencies": { "lodash-es": "4" }, @@ -5673,12 +5696,12 @@ "license": "MIT" }, "node_modules/next": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/next/-/next-15.5.7.tgz", - "integrity": "sha512-+t2/0jIJ48kUpGKkdlhgkv+zPTEOoXyr60qXe68eB/pl3CMJaLeIGjzp5D6Oqt25hCBiBTt8wEeeAzfJvUKnPQ==", + "version": "15.5.9", + "resolved": "https://registry.npmjs.org/next/-/next-15.5.9.tgz", + "integrity": "sha512-agNLK89seZEtC5zUHwtut0+tNrc0Xw4FT/Dg+B/VLEo9pAcS9rtTKpek3V6kVcVwsB2YlqMaHdfZL4eLEVYuCg==", "license": "MIT", "dependencies": { - "@next/env": "15.5.7", + "@next/env": "15.5.9", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", @@ -6228,9 +6251,10 @@ "license": "MIT" }, "node_modules/preact": { - "version": "10.26.4", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.26.4.tgz", - "integrity": "sha512-KJhO7LBFTjP71d83trW+Ilnjbo+ySsaAgCfXOXUlmGzJ4ygYPWmysm77yg4emwfmoz3b22yvH5IsVFHbhUaH5w==", + "version": "10.28.0", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.28.0.tgz", + "integrity": "sha512-rytDAoiXr3+t6OIP3WGlDd0ouCUG1iCWzkcY3++Nreuoi17y6T5i/zRhe6uYfoVcxq6YU+sBtJouuRDsq8vvqA==", + "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -6343,22 +6367,6 @@ "react": "^18.3.1" } }, - "node_modules/react-force-graph-2d": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/react-force-graph-2d/-/react-force-graph-2d-1.27.0.tgz", - "integrity": "sha512-NJAc7lWvY8PxBMn2uFXDDaeLcgJp37IYF6r0geOJlmMs5Lsf0IDmr35T7KNszHV3OUmTrZuPlyxrrzwGwyKhRg==", - "dependencies": { - "force-graph": "^1.49", - "prop-types": "15", - "react-kapsule": "^2.5" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "react": "*" - } - }, "node_modules/react-gtm-module": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/react-gtm-module/-/react-gtm-module-2.0.11.tgz", @@ -6383,20 +6391,6 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/react-kapsule": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/react-kapsule/-/react-kapsule-2.5.6.tgz", - "integrity": "sha512-aE4Nq7dDG8R/LdNmvOL6Azjr97I2E7ycFDJRkoHJSp9OQgTJDT3MHTJtJDrOTwzCl6sllYSqrtcndaCzizyAjQ==", - "dependencies": { - "jerrypick": "^1.1.1" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "react": ">=16.13.1" - } - }, "node_modules/react-remove-scroll": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz", @@ -7332,7 +7326,8 @@ "node_modules/tinycolor2": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", - "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", + "license": "MIT" }, "node_modules/to-regex-range": { "version": "5.0.1", diff --git a/package.json b/package.json index a24819ed..b30ce343 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "lint": "next lint" }, "dependencies": { + "@falkordb/canvas": "^0.0.6", "@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dropdown-menu": "^2.1.6", @@ -31,7 +32,6 @@ "playwright": "^1.49.1", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-force-graph-2d": "^1.27.0", "react-gtm-module": "^2.0.11", "react-json-tree": "^0.19.0", "react-resizable-panels": "^2.1.7", From 15859f744a206b3d072260577bb5cb2aa52ea012 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Thu, 18 Dec 2025 16:56:38 +0200 Subject: [PATCH 126/189] Update Next.js dependency to version 15.5.8 in package.json and package-lock.json --- package-lock.json | 16 ++++++++-------- package.json | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1eeadbdb..87cb3095 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,7 @@ "embla-carousel-react": "^8.5.2", "html2canvas": "^1.4.1", "lucide-react": "^0.486.0", - "next": "^15.5.5", + "next": "^15.5.8", "playwright": "^1.49.1", "react": "^18.3.1", "react-dom": "^18.3.1", @@ -874,9 +874,9 @@ } }, "node_modules/@next/env": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.7.tgz", - "integrity": "sha512-4h6Y2NyEkIEN7Z8YxkA27pq6zTkS09bUSYC0xjd0NpwFxjnIKeZEeH591o5WECSmjpUhLn3H2QLJcDye3Uzcvg==", + "version": "15.5.9", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.9.tgz", + "integrity": "sha512-4GlTZ+EJM7WaW2HEZcyU317tIQDjkQIyENDLxYJfSWlfqguN+dHkZgyQTV/7ykvobU7yEH5gKvreNrH4B6QgIg==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { @@ -5673,12 +5673,12 @@ "license": "MIT" }, "node_modules/next": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/next/-/next-15.5.7.tgz", - "integrity": "sha512-+t2/0jIJ48kUpGKkdlhgkv+zPTEOoXyr60qXe68eB/pl3CMJaLeIGjzp5D6Oqt25hCBiBTt8wEeeAzfJvUKnPQ==", + "version": "15.5.9", + "resolved": "https://registry.npmjs.org/next/-/next-15.5.9.tgz", + "integrity": "sha512-agNLK89seZEtC5zUHwtut0+tNrc0Xw4FT/Dg+B/VLEo9pAcS9rtTKpek3V6kVcVwsB2YlqMaHdfZL4eLEVYuCg==", "license": "MIT", "dependencies": { - "@next/env": "15.5.7", + "@next/env": "15.5.9", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", diff --git a/package.json b/package.json index a24819ed..bb052ea7 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "embla-carousel-react": "^8.5.2", "html2canvas": "^1.4.1", "lucide-react": "^0.486.0", - "next": "^15.5.5", + "next": "^15.5.8", "playwright": "^1.49.1", "react": "^18.3.1", "react-dom": "^18.3.1", From da9522f72378e5b711748322652b04f217270b43 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Thu, 18 Dec 2025 17:45:26 +0200 Subject: [PATCH 127/189] Refactor components to use canvasRef instead of chartRef for improved consistency and functionality --- app/components/ForceGraph.tsx | 9 +++++---- app/components/chat.tsx | 20 +++++++++---------- app/components/code-graph.tsx | 9 ++++----- app/components/graphView.tsx | 13 ++++++------- app/components/toolbar.tsx | 18 ++++++++++-------- app/page.tsx | 26 ++++++++++++------------- lib/utils.ts | 36 ++--------------------------------- 7 files changed, 50 insertions(+), 81 deletions(-) diff --git a/app/components/ForceGraph.tsx b/app/components/ForceGraph.tsx index 1312b28e..53109bbb 100644 --- a/app/components/ForceGraph.tsx +++ b/app/components/ForceGraph.tsx @@ -8,7 +8,7 @@ import { GraphData, Link, Node } from "./model" interface Props { data: GraphData canvasRef: GraphRef - onNodeClick?: (node: Node) => void + onNodeClick?: (node: Node, event: MouseEvent) => void onNodeRightClick?: (node: Node, event: MouseEvent) => void onLinkClick?: (link: Link, event: MouseEvent) => void onLinkRightClick?: (link: Link, event: MouseEvent) => void @@ -113,7 +113,7 @@ export default function ForceGraph({ const handleNodeClick = useCallback((node: any, event: MouseEvent) => { if (onNodeClick) { const originalNode = data.nodes.find(n => n.id === node.id) - if (originalNode) onNodeClick(originalNode) + if (originalNode) onNodeClick(originalNode, event) } }, [onNodeClick, data.nodes]) @@ -144,15 +144,16 @@ export default function ForceGraph({ // Update event handlers useEffect(() => { if (!canvasRef.current || !canvasLoaded) return + canvasRef.current.setConfig({ onNodeClick: handleNodeClick, onNodeRightClick: handleNodeRightClick, onLinkClick: handleLinkClick, onLinkRightClick: handleLinkRightClick, onBackgroundClick, - onBackgroundRightClick, + // onBackgroundRightClick, onEngineStop, - onZoom + // onZoom }) }, [ handleNodeClick, diff --git a/app/components/chat.tsx b/app/components/chat.tsx index f344244f..ef5e822d 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -2,9 +2,9 @@ import { toast } from "@/components/ui/use-toast"; import { Dispatch, FormEvent, MutableRefObject, SetStateAction, useEffect, useRef, useState } from "react"; import Image from "next/image"; import { AlignLeft, ArrowRight, ChevronDown, Lightbulb, Undo2 } from "lucide-react"; -import { handleZoomToFit, Message, MessageTypes, Path, PathData } from "@/lib/utils"; +import { Message, MessageTypes, Path, PathData } from "@/lib/utils"; import Input from "./Input"; -import { Graph, GraphData, Link, Node } from "./model"; +import { Graph, GraphData } from "./model"; import { cn, GraphRef } from "@/lib/utils"; import { TypeAnimation } from "react-type-animation"; import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; @@ -20,7 +20,7 @@ interface Props { isPathResponse: boolean | undefined setIsPathResponse: (isPathResponse: boolean | undefined) => void setData: Dispatch> - chartRef: GraphRef + canvasRef: GraphRef messages: Message[] setMessages: Dispatch> query: string @@ -51,7 +51,7 @@ const RemoveLastPath = (messages: Message[]) => { return messages } -export function Chat({ messages, setMessages, query, setQuery, selectedPath, setSelectedPath, setChatOpen, repo, path, setPath, graph, selectedPathId, isPathResponse, setIsPathResponse, setData, chartRef, paths, setPaths }: Props) { +export function Chat({ messages, setMessages, query, setQuery, selectedPath, setSelectedPath, setChatOpen, repo, path, setPath, graph, selectedPathId, isPathResponse, setIsPathResponse, setData, canvasRef, paths, setPaths }: Props) { const [sugOpen, setSugOpen] = useState(false); @@ -91,9 +91,9 @@ export function Chat({ messages, setMessages, query, setQuery, selectedPath, set }, [isPathResponse]) const handleSetSelectedPath = (p: PathData) => { - const chart = chartRef.current + const canvas = canvasRef.current - if (!chart) return + if (!canvas) return setSelectedPath(prev => { if (prev) { if (isPathResponse && paths.some((path) => [...path.nodes, ...path.links].every((e: any) => [...prev.nodes, ...prev.links].some((e: any) => e.id === e.id)))) { @@ -147,7 +147,7 @@ export function Chat({ messages, setMessages, query, setQuery, selectedPath, set } setData({ ...graph.Elements }) setTimeout(() => { - handleZoomToFit(chartRef, 2, (n: GraphNode) => p.nodes.some(node => node.id === n.id)); + canvas.zoomToFit(2, (n: GraphNode) => p.nodes.some(node => node.id === n.id)); }, 0) setChatOpen && setChatOpen(false) } @@ -206,9 +206,9 @@ export function Chat({ messages, setMessages, query, setQuery, selectedPath, set } const handleSubmit = async () => { - const chart = chartRef.current + const canvas = canvasRef.current - if (!chart) return + if (!canvas) return setSelectedPath(undefined) @@ -247,7 +247,7 @@ export function Chat({ messages, setMessages, query, setQuery, selectedPath, set setIsPathResponse(true) setData({ ...graph.Elements }) setTimeout(() => { - handleZoomToFit(chartRef, 2, (n: GraphNode) => formattedPaths.some(p => p.nodes.some(node => node.id === n.id))); + canvas.zoomToFit(2, (n: GraphNode) => formattedPaths.some(p => p.nodes.some(node => node.id === n.id))); }, 0) } diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index fdf31e5f..6d0c7503 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -27,7 +27,7 @@ interface Props { setOptions: Dispatch> isShowPath: boolean setPath: Dispatch> - chartRef: GraphRef + canvasRef: GraphRef selectedValue: string selectedPathId: number | undefined setSelectedPathId: (selectedPathId: number) => void @@ -54,7 +54,7 @@ export function CodeGraph({ setOptions, isShowPath, setPath, - chartRef, + canvasRef: chartRef, selectedValue, setSelectedPathId, isPathResponse, @@ -177,7 +177,7 @@ export function CodeGraph({ nodes: graph.Elements.nodes.filter(node => { if (!node.collapsed) return true - const isTarget = graph.Elements.links.some(link => link.target.id === node.id && nodes.some(n => n.id === link.source.id)); + const isTarget = graph.Elements.links.some(link => link.target === node.id && nodes.some(n => n.id === link.source)); if (!isTarget) return true @@ -332,7 +332,6 @@ export function CodeGraph({ selectedPathId={selectedPathId} setSelectedPathId={setSelectedPathId} cooldownTicks={cooldownTicks} - setCooldownTicks={setCooldownTicks} setZoomedNodes={setZoomedNodes} zoomedNodes={zoomedNodes} /> @@ -364,7 +363,7 @@ export function CodeGraph({ }
diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index ae13e38a..fe15c9ff 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -4,8 +4,9 @@ import { Graph, GraphData, Link, Node } from './model'; import { Dispatch, SetStateAction, useEffect, useRef, useState } from 'react'; import { Path } from '@/lib/utils'; import { Fullscreen } from 'lucide-react'; -import { GraphRef, handleZoomToFit } from '@/lib/utils'; +import { GraphRef } from '@/lib/utils'; import ForceGraph from './ForceGraph'; +import { GraphNode } from '@falkordb/canvas'; export interface Position { x: number, @@ -29,7 +30,6 @@ interface Props { selectedPathId: number | undefined setSelectedPathId: (selectedPathId: number) => void cooldownTicks: number | undefined - setCooldownTicks: Dispatch> setZoomedNodes: Dispatch> zoomedNodes: Node[] } @@ -37,7 +37,7 @@ interface Props { export default function GraphView({ data, graph, - chartRef, + chartRef: canvasRef, selectedObj, setSelectedObj, selectedObjects, @@ -50,7 +50,6 @@ export default function GraphView({ selectedPathId, setSelectedPathId, cooldownTicks, - setCooldownTicks, zoomedNodes, setZoomedNodes }: Props) { @@ -122,20 +121,20 @@ export default function GraphView({ } const handleEngineStop = () => { - handleZoomToFit(chartRef, zoomedNodes.length === 1 ? 4 : 1, (n: any) => zoomedNodes.some(node => node.id === n.id)) + canvasRef.current?.zoomToFit(zoomedNodes.length === 1 ? 4 : 1, (n: GraphNode) => zoomedNodes.some(node => node.id === n.id)) setZoomedNodes([]) } return (
-
Number(process.env.NEXT_PUBLIC_MOBILE_BREAKPOINT) || isShowPath ? (node: Node, _evt: MouseEvent) => handleNodeClick(node) : (node: Node, evt: MouseEvent) => handleRightClick(node, evt)} onNodeRightClick={handleRightClick} onLinkClick={screenSize > Number(process.env.NEXT_PUBLIC_MOBILE_BREAKPOINT) && isPathResponse ? handleLinkClick : handleRightClick} diff --git a/app/components/toolbar.tsx b/app/components/toolbar.tsx index 9769f25e..10b3404b 100644 --- a/app/components/toolbar.tsx +++ b/app/components/toolbar.tsx @@ -3,24 +3,26 @@ import { cn } from "@/lib/utils" import { GraphRef } from "@/lib/utils"; interface Props { - chartRef: GraphRef + canvasRef: GraphRef className?: string handleDownloadImage?: () => void } -export function Toolbar({ chartRef, className, handleDownloadImage }: Props) { +export function Toolbar({ canvasRef, className, handleDownloadImage }: Props) { const handleZoomClick = (changefactor: number) => { - const chart = chartRef.current - if (chart) { - chart.zoom(chart.zoom() * changefactor) + const canvas = canvasRef.current + + if (canvas) { + canvas.zoom(canvas.getZoom() * changefactor) } } const handleCenterClick = () => { - const chart = chartRef.current - if (chart) { - chart.zoomToFit(1000, 40) + const canvas = canvasRef.current + + if (canvas) { + canvas.zoomToFit() } } diff --git a/app/page.tsx b/app/page.tsx index 9d4144a9..cfbef292 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -19,8 +19,8 @@ import { Drawer, DrawerContent, DrawerDescription, DrawerTitle, DrawerTrigger } import Input from './components/Input'; import { Labels } from './components/labels'; import { Toolbar } from './components/toolbar'; -import { cn, GraphRef, handleZoomToFit, Message, Path, PathData, PathNode } from '@/lib/utils'; -import { GraphContext } from './components/provider'; +import { cn, GraphRef, Message, Path, PathData, PathNode } from '@/lib/utils'; +import { GraphNode } from '@falkordb/canvas'; type Tip = { title: string @@ -66,8 +66,8 @@ export default function Home() { const [options, setOptions] = useState([]); const [path, setPath] = useState(); const [isSubmit, setIsSubmit] = useState(false); - const desktopChartRef = useRef() - const mobileChartRef = useRef() + const desktopChartRef = useRef(null) + const mobileChartRef = useRef(null) const [menuOpen, setMenuOpen] = useState(false) const [chatOpen, setChatOpen] = useState(false) const [searchNode, setSearchNode] = useState({}); @@ -189,10 +189,10 @@ export default function Home() { return graph.extend(json.result.neighbors, true) } - const handleSearchSubmit = (node: any, chartRef: GraphRef) => { - const chart = chartRef.current + const handleSearchSubmit = (node: any, canvasRef: GraphRef) => { + const canvas = canvasRef.current - if (chart) { + if (canvas) { let chartNode = graph.Elements.nodes.find(n => n.id == node.id) if (!chartNode?.visible) { @@ -210,7 +210,7 @@ export default function Home() { } setTimeout(() => { - handleZoomToFit(chartRef, 4, (n: GraphNode) => n.id === chartNode!.id) + canvas.zoomToFit(4, (n: GraphNode) => n.id === chartNode!.id) }, 0) setSearchNode(chartNode) setOptionsOpen(false) @@ -389,7 +389,7 @@ export default function Home() { graph={graph} data={data} setData={setData} - chartRef={desktopChartRef} + canvasRef={desktopChartRef} options={options} setOptions={setOptions} onFetchGraph={onFetchGraph} @@ -428,7 +428,7 @@ export default function Home() { setQuery={setQuery} selectedPath={selectedPath} setSelectedPath={setSelectedPath} - chartRef={desktopChartRef} + canvasRef={desktopChartRef} setPath={setPath} path={path} repo={graph.Id} @@ -507,7 +507,7 @@ export default function Home() { graph={graph} data={data} setData={setData} - chartRef={mobileChartRef} + canvasRef={mobileChartRef} options={options} setOptions={setOptions} onFetchGraph={onFetchGraph} @@ -549,7 +549,7 @@ export default function Home() { setQuery={setQuery} selectedPath={selectedPath} setSelectedPath={setSelectedPath} - chartRef={mobileChartRef} + canvasRef={mobileChartRef} setPath={setPath} path={path} repo={graph.Id} @@ -577,7 +577,7 @@ export default function Home() { +export type GraphRef = MutableRefObject export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } - -export function handleZoomToFit(chartRef: GraphRef, paddingMultiplier = 1, filter?: (node: NodeGraph) => boolean) { - const chart = chartRef.current - if (chart) { - // Find the currently visible canvas by checking display property - const canvases = document.querySelectorAll('.force-graph-container canvas') as NodeListOf; - const container = Array.from(canvases).find(canvas => { - const container = canvas.parentElement; - - if (!container) return false; - - // Check if element is actually in viewport - const rect = container.getBoundingClientRect(); - const isInViewport = rect.width > 0 && - rect.height > 0 && - rect.top >= 0 && - rect.left >= 0 && - rect.bottom <= window.innerHeight && - rect.right <= window.innerWidth; - - return isInViewport; - })?.parentElement; - - if (!container) return; - - // Calculate padding as 10% of the smallest canvas dimension - const minDimension = Math.min(container.clientWidth, container.clientHeight); - - const padding = minDimension * 0.1 * paddingMultiplier; - - chart.zoomToFit(1000, padding, filter); - } -} \ No newline at end of file From 39e074fbfac04ec9892eaf94207a166b94090ee3 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Thu, 18 Dec 2025 17:47:46 +0200 Subject: [PATCH 128/189] Update FalkorDB canvas dependency to version 0.0.7 and enable background right-click and zoom functionalities in ForceGraph component --- app/components/ForceGraph.tsx | 4 ++-- package-lock.json | 8 ++++---- package.json | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/components/ForceGraph.tsx b/app/components/ForceGraph.tsx index 53109bbb..297c4eab 100644 --- a/app/components/ForceGraph.tsx +++ b/app/components/ForceGraph.tsx @@ -151,9 +151,9 @@ export default function ForceGraph({ onLinkClick: handleLinkClick, onLinkRightClick: handleLinkRightClick, onBackgroundClick, - // onBackgroundRightClick, + onBackgroundRightClick, onEngineStop, - // onZoom + onZoom }) }, [ handleNodeClick, diff --git a/package-lock.json b/package-lock.json index bb1f5672..6d13c2c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "code-graph", "version": "0.2.0", "dependencies": { - "@falkordb/canvas": "^0.0.6", + "@falkordb/canvas": "^0.0.7", "@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dropdown-menu": "^2.1.6", @@ -217,9 +217,9 @@ } }, "node_modules/@falkordb/canvas": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@falkordb/canvas/-/canvas-0.0.6.tgz", - "integrity": "sha512-5r2dEt3O05dz5drfzHUxEShjqAi1kkDMUadvgBV3rq2YOlZmU9vAOYneU0mpAU1UJOprc+yc78xjTEGMict3Vw==", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@falkordb/canvas/-/canvas-0.0.7.tgz", + "integrity": "sha512-EGUz7xUO17+LL89dbO4Uy3ySeHmNxBN8x78b5tbHVNrQJ5kpRyTFGtKH3KqgYSkk5N4PxCxLs2AMK1GBujFjpQ==", "license": "MIT", "dependencies": { "d3": "^7.9.0", diff --git a/package.json b/package.json index b30ce343..9f7c91d7 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "lint": "next lint" }, "dependencies": { - "@falkordb/canvas": "^0.0.6", + "@falkordb/canvas": "^0.0.7", "@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dropdown-menu": "^2.1.6", From b0fb8f5475536b64ee44d6bc2816fcdb97895cbd Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Wed, 24 Dec 2025 14:12:31 +0200 Subject: [PATCH 129/189] Update FalkorDB canvas dependency to version 0.0.8 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6d13c2c4..de1d59b9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "code-graph", "version": "0.2.0", "dependencies": { - "@falkordb/canvas": "^0.0.7", + "@falkordb/canvas": "^0.0.8", "@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dropdown-menu": "^2.1.6", @@ -217,9 +217,9 @@ } }, "node_modules/@falkordb/canvas": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@falkordb/canvas/-/canvas-0.0.7.tgz", - "integrity": "sha512-EGUz7xUO17+LL89dbO4Uy3ySeHmNxBN8x78b5tbHVNrQJ5kpRyTFGtKH3KqgYSkk5N4PxCxLs2AMK1GBujFjpQ==", + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@falkordb/canvas/-/canvas-0.0.8.tgz", + "integrity": "sha512-vPHEpwr7D06qUrxSbSovnH8lTdbRahlQ+wi0Hv0e7++xqvNGapMZLICrjblh/oyO2H+Ce823nTh3qZtarjdkeQ==", "license": "MIT", "dependencies": { "d3": "^7.9.0", diff --git a/package.json b/package.json index 9f7c91d7..8b6b8233 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "lint": "next lint" }, "dependencies": { - "@falkordb/canvas": "^0.0.7", + "@falkordb/canvas": "^0.0.8", "@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dropdown-menu": "^2.1.6", From 3f68425f8076a2353f5e836d253e39b7b62953d0 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Tue, 30 Dec 2025 12:48:57 +0200 Subject: [PATCH 130/189] Update FalkorDB canvas dependency to version 0.0.11 and improve error handling in API routes --- app/api/repo/route.ts | 4 +-- app/components/ForceGraph.tsx | 50 +++++++---------------------------- package-lock.json | 16 +++++------ package.json | 4 +-- 4 files changed, 21 insertions(+), 53 deletions(-) diff --git a/app/api/repo/route.ts b/app/api/repo/route.ts index 421be274..f4f667f1 100644 --- a/app/api/repo/route.ts +++ b/app/api/repo/route.ts @@ -22,7 +22,7 @@ export async function GET() { return NextResponse.json({ result: repositories }, { status: 200 }) } catch (err) { console.error(err) - return NextResponse.json((err as Error).message, { status: 400 }) + return NextResponse.json(err instanceof Error ? err.message : err, { status: 400 }) } } @@ -57,6 +57,6 @@ export async function POST(request: NextRequest) { return NextResponse.json({ message: "success" }, { status: 200 }); } catch (err) { console.error(err) - return NextResponse.json((err as Error).message, { status: 400 }); + return NextResponse.json(err instanceof Error ? err.message : err, { status: 400 }); } } \ No newline at end of file diff --git a/app/components/ForceGraph.tsx b/app/components/ForceGraph.tsx index 297c4eab..50b39d2b 100644 --- a/app/components/ForceGraph.tsx +++ b/app/components/ForceGraph.tsx @@ -57,10 +57,7 @@ export default function ForceGraph({ backgroundColor = "#FFFFFF", foregroundColor = "#000000" }: Props) { - const parentRef = useRef(null) const [canvasLoaded, setCanvasLoaded] = useState(false) - const [parentWidth, setParentWidth] = useState(0) - const [parentHeight, setParentHeight] = useState(0) // Load falkordb-canvas dynamically (client-only) useEffect(() => { @@ -69,33 +66,6 @@ export default function ForceGraph({ }) }, []) - // Handle parent resize - useEffect(() => { - const handleResize = () => { - if (!parentRef.current) return - setParentWidth(parentRef.current.clientWidth) - setParentHeight(parentRef.current.clientHeight) - } - - handleResize() - - const observer = new ResizeObserver(handleResize) - if (parentRef.current) { - observer.observe(parentRef.current) - } - - return () => { - observer.disconnect() - } - }, []) - - // Update canvas dimensions - useEffect(() => { - if (!canvasRef.current || !canvasLoaded) return - canvasRef.current.setWidth(parentWidth) - canvasRef.current.setHeight(parentHeight) - }, [canvasRef, parentWidth, parentHeight, canvasLoaded]) - // Update canvas colors useEffect(() => { if (!canvasRef.current || !canvasLoaded) return @@ -144,7 +114,7 @@ export default function ForceGraph({ // Update event handlers useEffect(() => { if (!canvasRef.current || !canvasLoaded) return - + canvasRef.current.setConfig({ onNodeClick: handleNodeClick, onNodeRightClick: handleNodeRightClick, @@ -156,15 +126,15 @@ export default function ForceGraph({ onZoom }) }, [ - handleNodeClick, - handleNodeRightClick, - handleLinkClick, - handleLinkRightClick, - onBackgroundClick, - onBackgroundRightClick, + handleNodeClick, + handleNodeRightClick, + handleLinkClick, + handleLinkRightClick, + onBackgroundClick, + onBackgroundRightClick, onEngineStop, onZoom, - canvasRef, + canvasRef, canvasLoaded ]) @@ -178,8 +148,6 @@ export default function ForceGraph({ }, [canvasRef, data, canvasLoaded]) return ( -
- -
+ ) } diff --git a/package-lock.json b/package-lock.json index de1d59b9..0065a0c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "code-graph", "version": "0.2.0", "dependencies": { - "@falkordb/canvas": "^0.0.8", + "@falkordb/canvas": "^0.0.11", "@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dropdown-menu": "^2.1.6", @@ -42,7 +42,7 @@ }, "devDependencies": { "@playwright/test": "^1.50.1", - "@types/node": "^22.15.26", + "@types/node": "^20.19.4", "@types/react": "^18.3.18", "@types/react-dom": "^18.3.5", "@types/react-syntax-highlighter": "^15.5.13", @@ -217,9 +217,9 @@ } }, "node_modules/@falkordb/canvas": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@falkordb/canvas/-/canvas-0.0.8.tgz", - "integrity": "sha512-vPHEpwr7D06qUrxSbSovnH8lTdbRahlQ+wi0Hv0e7++xqvNGapMZLICrjblh/oyO2H+Ce823nTh3qZtarjdkeQ==", + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/@falkordb/canvas/-/canvas-0.0.11.tgz", + "integrity": "sha512-Wc+p2+u24+OKBZ3i8BRBJdArEpuay4n9EDoeLnrf1tcWV4oIW7amRatc5a+eIuPF3vrsGJdzWbpWC2/X7MLVyQ==", "license": "MIT", "dependencies": { "d3": "^7.9.0", @@ -1953,9 +1953,9 @@ "integrity": "sha512-jsxagdikDiDBeIRaPYtArcT8my4tN1og7MtMRquFT3XNA6axxyHDRUemqDz/taRDdOUn0GnGHRCuff4q48sW9A==" }, "node_modules/@types/node": { - "version": "22.19.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.2.tgz", - "integrity": "sha512-LPM2G3Syo1GLzXLGJAKdqoU35XvrWzGJ21/7sgZTUpbkBaOasTj8tjwn6w+hCkqaa1TfJ/w67rJSwYItlJ2mYw==", + "version": "20.19.27", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.27.tgz", + "integrity": "sha512-N2clP5pJhB2YnZJ3PIHFk5RkygRX5WO/5f0WC08tp0wd+sv0rsJk3MqWn3CbNmT2J505a5336jaQj4ph1AdMug==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 8b6b8233..6414a751 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "lint": "next lint" }, "dependencies": { - "@falkordb/canvas": "^0.0.8", + "@falkordb/canvas": "^0.0.11", "@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dropdown-menu": "^2.1.6", @@ -43,7 +43,7 @@ }, "devDependencies": { "@playwright/test": "^1.50.1", - "@types/node": "^22.15.26", + "@types/node": "^20.19.4", "@types/react": "^18.3.18", "@types/react-dom": "^18.3.5", "@types/react-syntax-highlighter": "^15.5.13", From f9d16ad277effeaa0da0a54128e96c25f5e81618 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Tue, 30 Dec 2025 13:52:26 +0200 Subject: [PATCH 131/189] Refactor ForceGraph and CodeGraph components to integrate cooldown ticks state management and update FalkorDB canvas dependency to version 0.0.12 --- app/components/ForceGraph.tsx | 1 - app/components/code-graph.tsx | 3 + app/components/graphView.tsx | 6 +- app/components/toolbar.tsx | 18 +- app/page.tsx | 2 + components/ui/switch.tsx | 29 +++ package-lock.json | 390 ++++++++++++++++++++-------------- package.json | 3 +- 8 files changed, 284 insertions(+), 168 deletions(-) create mode 100644 components/ui/switch.tsx diff --git a/app/components/ForceGraph.tsx b/app/components/ForceGraph.tsx index 50b39d2b..522e47f6 100644 --- a/app/components/ForceGraph.tsx +++ b/app/components/ForceGraph.tsx @@ -52,7 +52,6 @@ export default function ForceGraph({ onBackgroundRightClick, onZoom, onEngineStop, - onNodeDragEnd, cooldownTicks, backgroundColor = "#FFFFFF", foregroundColor = "#000000" diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 6d0c7503..f7f1f9b7 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -332,6 +332,7 @@ export function CodeGraph({ selectedPathId={selectedPathId} setSelectedPathId={setSelectedPathId} cooldownTicks={cooldownTicks} + setCooldownTicks={setCooldownTicks} setZoomedNodes={setZoomedNodes} zoomedNodes={zoomedNodes} /> @@ -365,6 +366,8 @@ export function CodeGraph({ className="gap-4" canvasRef={chartRef} handleDownloadImage={handleDownloadImage} + setCooldownTicks={setCooldownTicks} + cooldownTicks={cooldownTicks} />
diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index fe15c9ff..4ca440e2 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -30,13 +30,13 @@ interface Props { selectedPathId: number | undefined setSelectedPathId: (selectedPathId: number) => void cooldownTicks: number | undefined + setCooldownTicks: Dispatch> setZoomedNodes: Dispatch> zoomedNodes: Node[] } export default function GraphView({ data, - graph, chartRef: canvasRef, selectedObj, setSelectedObj, @@ -50,6 +50,7 @@ export default function GraphView({ selectedPathId, setSelectedPathId, cooldownTicks, + setCooldownTicks, zoomedNodes, setZoomedNodes }: Props) { @@ -121,8 +122,11 @@ export default function GraphView({ } const handleEngineStop = () => { + if (cooldownTicks === 0) return + canvasRef.current?.zoomToFit(zoomedNodes.length === 1 ? 4 : 1, (n: GraphNode) => zoomedNodes.some(node => node.id === n.id)) setZoomedNodes([]) + setCooldownTicks(0) } return ( diff --git a/app/components/toolbar.tsx b/app/components/toolbar.tsx index 10b3404b..1327febd 100644 --- a/app/components/toolbar.tsx +++ b/app/components/toolbar.tsx @@ -1,18 +1,21 @@ import { Download, Fullscreen, ZoomIn, ZoomOut } from "lucide-react"; import { cn } from "@/lib/utils" import { GraphRef } from "@/lib/utils"; +import { Switch } from "@/components/ui/switch"; interface Props { canvasRef: GraphRef className?: string handleDownloadImage?: () => void + setCooldownTicks: (ticks?: 0) => void + cooldownTicks: number | undefined } -export function Toolbar({ canvasRef, className, handleDownloadImage }: Props) { +export function Toolbar({ canvasRef, className, handleDownloadImage, setCooldownTicks, cooldownTicks }: Props) { const handleZoomClick = (changefactor: number) => { const canvas = canvasRef.current - + if (canvas) { canvas.zoom(canvas.getZoom() * changefactor) } @@ -20,14 +23,21 @@ export function Toolbar({ canvasRef, className, handleDownloadImage }: Props) { const handleCenterClick = () => { const canvas = canvasRef.current - + if (canvas) { canvas.zoomToFit() } } return ( -
+
+ { + setCooldownTicks(cooldownTicks === undefined ? 0 : undefined) + }} + /> @@ -89,11 +90,11 @@ export default function ElementMenu({ obj, objects, setPath, handleRemove, posit title="Copy src to clipboard" onClick={async () => { try { - await navigator.clipboard.writeText(obj.src || ""); + await navigator.clipboard.writeText(obj.data.src || ""); } catch (err) { // Fallback for older browsers const textArea = document.createElement('textarea'); - textArea.value = obj.src || ""; + textArea.value = obj.data.src || ""; textArea.style.position = 'fixed'; textArea.style.left = '-999999px'; document.body.appendChild(textArea); diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 4ca440e2..fba164ad 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -1,12 +1,12 @@ 'use client' import { Graph, GraphData, Link, Node } from './model'; -import { Dispatch, SetStateAction, useEffect, useRef, useState } from 'react'; -import { Path } from '@/lib/utils'; +import { Dispatch, SetStateAction, useCallback, useEffect, useRef, useState } from 'react'; +import { Path, PATH_COLOR } from '@/lib/utils'; import { Fullscreen } from 'lucide-react'; import { GraphRef } from '@/lib/utils'; import ForceGraph from './ForceGraph'; -import { GraphNode } from '@falkordb/canvas'; +import { GraphLink, GraphNode } from '@falkordb/canvas'; export interface Position { x: number, @@ -23,7 +23,7 @@ interface Props { selectedObjects: Node[] setSelectedObjects: Dispatch> setPosition: Dispatch> - handleExpand: (nodes: Node[], expand: boolean) => void + handleExpand: (nodes: Node[], expand: boolean) => void isShowPath: boolean setPath: Dispatch> isPathResponse: boolean | undefined @@ -35,8 +35,12 @@ interface Props { zoomedNodes: Node[] } +const NODE_SIZE = 6; +const PADDING = 2; + export default function GraphView({ data, + graph, chartRef: canvasRef, selectedObj, setSelectedObj, @@ -72,13 +76,13 @@ export default function GraphView({ } }, []) - const unsetSelectedObjects = (evt?: MouseEvent) => { + const unsetSelectedObjects = useCallback((evt?: MouseEvent) => { if (evt?.ctrlKey || (!selectedObj && selectedObjects.length === 0)) return setSelectedObj(undefined) setSelectedObjects([]) - } + }, [selectedObj, selectedObjects, setSelectedObj, setSelectedObjects]) - const handleRightClick = (element: Node | Link, evt: MouseEvent) => { + const handleRightClick = useCallback((element: Node | Link, evt: MouseEvent) => { if (evt.ctrlKey && "category" in element) { if (selectedObjects.some(obj => obj.id === element.id)) { setSelectedObjects(selectedObjects.filter(obj => obj.id !== element.id)) @@ -92,7 +96,7 @@ export default function GraphView({ setSelectedObj(element) setPosition({ x: evt.clientX, y: evt.clientY }) - } + }, [selectedObjects, setSelectedObjects, setSelectedObj, setPosition]) const handleLinkClick = (link: Link, evt: MouseEvent) => { unsetSelectedObjects(evt) @@ -100,34 +104,220 @@ export default function GraphView({ setSelectedPathId(link.id) } - const handleNodeClick = async (node: Node) => { + const handleNodeClick = useCallback(async (node: Node) => { const now = new Date() const { date, name } = lastClick.current - const isDoubleClick = now.getTime() - date.getTime() < 1000 && name === node.name - lastClick.current = { date: now, name: node.name } + const isDoubleClick = now.getTime() - date.getTime() < 1000 && name === node.data.name + lastClick.current = { date: now, name: node.data.name } if (isDoubleClick) { handleExpand([node], !node.expand) } else if (isShowPath) { setPath(prev => { if (!prev?.start?.name || (prev.end?.name && prev.end?.name !== "")) { - return ({ start: { id: Number(node.id), name: node.name } }) + return ({ start: { id: Number(node.id), name: node.data.name } }) } else { - return ({ end: { id: Number(node.id), name: node.name }, start: prev.start }) + return ({ end: { id: Number(node.id), name: node.data.name }, start: prev.start }) } }) return } - } + }, [handleExpand, isShowPath, setPath]) - const handleEngineStop = () => { - if (cooldownTicks === 0) return + const handleEngineStop = useCallback(() => { + if (zoomedNodes.length > 0) { + canvasRef.current?.zoomToFit(zoomedNodes.length === 1 ? 4 : 1, (n: GraphNode) => zoomedNodes.some(node => node.id === n.id)) + setZoomedNodes([]) + } + + if (cooldownTicks !== -1) return - canvasRef.current?.zoomToFit(zoomedNodes.length === 1 ? 4 : 1, (n: GraphNode) => zoomedNodes.some(node => node.id === n.id)) - setZoomedNodes([]) setCooldownTicks(0) - } + }, [zoomedNodes, cooldownTicks, canvasRef]) + + const nodeCanvasObject = useCallback((node: GraphNode, ctx: CanvasRenderingContext2D) => { + if (!node.x || !node.y) return + + if (isPathResponse) { + if (node.data.isPathSelected) { + ctx.fillStyle = node.color; + ctx.strokeStyle = PATH_COLOR; + ctx.lineWidth = 1.5 + } else if (node.data.isPath) { + ctx.fillStyle = node.color; + ctx.strokeStyle = PATH_COLOR; + ctx.lineWidth = 1 + } else { + ctx.fillStyle = '#E5E5E5'; + ctx.strokeStyle = 'gray'; + ctx.lineWidth = 1 + } + } else if (isPathResponse === undefined) { + if (node.data.isPathSelected) { + ctx.fillStyle = node.color; + ctx.strokeStyle = PATH_COLOR; + ctx.lineWidth = 1.5 + } else if (node.data.isPath) { + ctx.fillStyle = node.color; + ctx.strokeStyle = PATH_COLOR; + ctx.lineWidth = 1 + } else { + ctx.fillStyle = node.color; + ctx.strokeStyle = 'black'; + ctx.lineWidth = selectedObjects.some(obj => obj.id === node.id) || selectedObj?.id === node.id ? 1.5 : 1 + } + } else { + ctx.fillStyle = node.color; + ctx.strokeStyle = 'black'; + ctx.lineWidth = selectedObjects.some(obj => obj.id === node.id) || selectedObj?.id === node.id ? 1.5 : 1 + } + + ctx.beginPath(); + ctx.arc(node.x, node.y, NODE_SIZE + ctx.lineWidth / 2, 0, 2 * Math.PI, false); + ctx.stroke(); + ctx.fill(); + + ctx.fillStyle = 'black'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.font = '4px Arial'; + let name = node.data.name || ""; + const textWidth = ctx.measureText(name).width; + const ellipsis = '...'; + const ellipsisWidth = ctx.measureText(ellipsis).width; + const nodeSize = (NODE_SIZE + ctx.lineWidth / 2) * 2 - PADDING; + + // truncate text if it's too long + if (textWidth > nodeSize) { + while (name.length > 0 && ctx.measureText(name).width + ellipsisWidth > nodeSize) { + name = name.slice(0, -1); + } + name += ellipsis; + } + + // add label + ctx.fillText(name, node.x, node.y); + }, [selectedObj, selectedObjects, isPathResponse]) + + const nodePointerAreaPaint = useCallback((node: GraphNode, color: string, ctx: CanvasRenderingContext2D) => { + if (!node.x || !node.y) return + + ctx.fillStyle = color; + ctx.beginPath(); + ctx.arc(node.x, node.y, NODE_SIZE + 4 + ctx.lineWidth / 2, 0, 2 * Math.PI, false); + ctx.fill(); + }, []) + + const linkCanvasObject = useCallback((link: GraphLink, ctx: CanvasRenderingContext2D) => { + const start = link.source; + const end = link.target; + + if (!start.x || !start.y || !end.x || !end.y) return + + const sameNodesLinks = graph.Elements.links.filter(l => (l.source === start.id && l.target === end.id) || (l.target === start.id && l.source === end.id)) + const index = sameNodesLinks.findIndex(l => l.id === link.id) || 0 + const even = index % 2 === 0 + let curve + + if (start.id === end.id) { + if (even) { + curve = Math.floor(-(index / 2)) - 3 + } else { + curve = Math.floor((index + 1) / 2) + 2 + } + + link.curve = curve * 0.1 + + const radius = NODE_SIZE * link.curve * 6.2; + const angleOffset = -Math.PI / 4; // 45 degrees offset for text alignment + const textX = start.x + radius * Math.cos(angleOffset); + const textY = start.y + radius * Math.sin(angleOffset); + + ctx.save(); + ctx.translate(textX, textY); + ctx.rotate(-angleOffset); + } else { + if (even) { + curve = Math.floor(-(index / 2)) + } else { + curve = Math.floor((index + 1) / 2) + } + + link.curve = curve * 0.1 + + const midX = (start.x + end.x) / 2 + (end.y - start.y) * (link.curve / 2); + const midY = (start.y + end.y) / 2 + (start.x - end.x) * (link.curve / 2); + + let textAngle = Math.atan2(end.y - start.y, end.x - start.x) + + // maintain label vertical orientation for legibility + if (textAngle > Math.PI / 2) textAngle = -(Math.PI - textAngle); + if (textAngle < -Math.PI / 2) textAngle = -(-Math.PI - textAngle); + + ctx.save(); + ctx.translate(midX, midY); + ctx.rotate(textAngle); + } + + // add label + ctx.globalAlpha = 1; + ctx.fillStyle = 'black'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.font = '2px Arial'; + ctx.fillText(link.relationship, 0, 0); + ctx.restore() + }, [graph.Elements.links]) + + const linkPointerAreaPaint = useCallback((link: GraphLink, color: string, ctx: CanvasRenderingContext2D) => { + const start = link.source; + const end = link.target; + + if (!start.x || !start.y || !end.x || !end.y) return + + ctx.fillStyle = color; + + // Calculate curve the same way as linkCanvasObject + const sameNodesLinks = graph.Elements.links.filter(l => (l.source === start.id && l.target === end.id) || (l.target === start.id && l.source === end.id)) + const index = sameNodesLinks.findIndex(l => l.id === link.id) || 0 + const even = index % 2 === 0 + let curve + + if (start.id === end.id) { + // Self-loop: draw clickable area at the loop position + if (even) { + curve = Math.floor(-(index / 2)) - 3 + } else { + curve = Math.floor((index + 1) / 2) + 2 + } + + const curvature = curve * 0.1 + const radius = NODE_SIZE * curvature * 6.2; + const angleOffset = -Math.PI / 4; + const textX = start.x + radius * Math.cos(angleOffset); + const textY = start.y + radius * Math.sin(angleOffset); + + ctx.beginPath(); + ctx.arc(textX, textY, 5, 0, 2 * Math.PI, false); + ctx.fill(); + } else { + // Regular link: draw clickable area at the curve midpoint + if (even) { + curve = Math.floor(-(index / 2)) + } else { + curve = Math.floor((index + 1) / 2) + } + + const curvature = curve * 0.1 + const midX = (start.x + end.x) / 2 + (end.y - start.y) * (curvature / 2); + const midY = (start.y + end.y) / 2 + (start.x - end.x) * (curvature / 2); + + ctx.beginPath(); + ctx.arc(midX, midY, 5, 0, 2 * Math.PI, false); + ctx.fill(); + } + }, [graph.Elements.links]) return (
@@ -147,6 +337,10 @@ export default function GraphView({ onBackgroundRightClick={unsetSelectedObjects} onZoom={() => unsetSelectedObjects()} onEngineStop={handleEngineStop} + nodeCanvasObject={nodeCanvasObject} + nodePointerAreaPaint={nodePointerAreaPaint} + linkCanvasObject={linkCanvasObject} + linkPointerAreaPaint={linkPointerAreaPaint} cooldownTicks={cooldownTicks} />
diff --git a/app/components/model.ts b/app/components/model.ts index 7a9274bd..6875f941 100644 --- a/app/components/model.ts +++ b/app/components/model.ts @@ -16,7 +16,6 @@ export interface Label { export interface Node { id: number, - name: string, category: string, color: string, visible: boolean, @@ -24,9 +23,11 @@ export interface Node { expand: boolean, isPathSelected: boolean, isPath: boolean, - [key: string]: any, + data: { + name: string, + [key: string]: any, + } } - export interface Link { id: number, source: number, @@ -35,9 +36,10 @@ export interface Link { visible: boolean, isPathSelected: boolean, isPath: boolean, - curve: number, color: string, - [key: string]: any, + data: { + [key: string]: any, + }, } const COLORS_ORDER_NAME = [ @@ -161,18 +163,18 @@ export class Graph { node = { id: nodeData.id, - name: nodeData.name, color: getCategoryColorValue(category.index), category: category.name, expand: false, visible: true, collapsed, isPath: !!path, - isPathSelected: path?.start?.id === nodeData.id || path?.end?.id === nodeData.id + isPathSelected: path?.start?.id === nodeData.id || path?.end?.id === nodeData.id, + data: { + ...nodeData.properties, + } } - Object.entries(nodeData.properties).forEach(([key, value]) => { - node[key] = value - }) + this.nodesMap.set(nodeData.id, node) this.elements.nodes.push(node) newElements.nodes.push(node) @@ -195,14 +197,17 @@ export class Graph { if (!source) { source = { id: edgeData.src_node, - name: edgeData.src_node, color: getCategoryColorValue(), category: "", expand: false, visible: true, collapsed, isPath: !!path, - isPathSelected: path?.start?.id === edgeData.src_node || path?.end?.id === edgeData.src_node + isPathSelected: path?.start?.id === edgeData.src_node || path?.end?.id === edgeData.src_node, + data: { + name: edgeData.src_node + } + } this.nodesMap.set(edgeData.src_node, source) } @@ -210,14 +215,16 @@ export class Graph { if (!target) { target = { id: edgeData.dest_node, - name: edgeData.dest_node, color: getCategoryColorValue(), category: "", expand: false, visible: true, collapsed, isPath: !!path, - isPathSelected: path?.start?.id === edgeData.dest_node || path?.end?.id === edgeData.dest_node + isPathSelected: path?.start?.id === edgeData.dest_node || path?.end?.id === edgeData.dest_node, + data: { + name: edgeData.dest_node + } } this.nodesMap.set(edgeData.dest_node, target) } @@ -235,45 +242,17 @@ export class Graph { target: edgeData.dest_node, label: edgeData.relation, visible: true, - expand: false, color: "#999999", - collapsed, isPathSelected: false, isPath: !!path, - curve: 0 + data: { ...edgeData.properties } } + this.linksMap.set(edgeData.id, link) this.elements.links.push(link) newElements.links.push(link) }) - newElements.links.forEach(link => { - const start = link.source - const end = link.target - const sameNodesLinks = this.elements.links.filter(l => (l.source === start && l.target === end) || (l.target === start && l.source === end)) - const index = sameNodesLinks.findIndex(l => l.id === link.id) ?? 0 - const even = index % 2 === 0 - let curve - - if (start === end) { - if (even) { - curve = Math.floor(-(index / 2)) - 3 - } else { - curve = Math.floor((index + 1) / 2) + 2 - } - } else { - if (even) { - curve = Math.floor(-(index / 2)) - } else { - curve = Math.floor((index + 1) / 2) - } - - } - - link.curve = curve * 0.1 - }) - - return newElements } diff --git a/app/components/toolbar.tsx b/app/components/toolbar.tsx index 1327febd..b4d11258 100644 --- a/app/components/toolbar.tsx +++ b/app/components/toolbar.tsx @@ -33,9 +33,9 @@ export function Toolbar({ canvasRef, className, handleDownloadImage, setCooldown
{ - setCooldownTicks(cooldownTicks === undefined ? 0 : undefined) + setCooldownTicks(cooldownTicks !== 0 ? 0 : undefined) }} /> } { - (graph.getElements().some(e => !e.visible)) && + hasHiddenElements &&
Number(process.env.NEXT_PUBLIC_MOBILE_BREAKPOINT) || isShowPath ? (node: Node, _evt: MouseEvent) => handleNodeClick(node) : (node: Node, evt: MouseEvent) => handleRightClick(node, evt)} diff --git a/app/page.tsx b/app/page.tsx index 49b4fb05..edc5b978 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -142,32 +142,37 @@ export default function Home() { } async function onFetchGraph(graphName: string) { + try { + const result = await fetch(`/api/repo/${prepareArg(graphName)}`, { + method: 'GET' + }) + + if (!result.ok) { + toast({ + variant: "destructive", + title: "Uh oh! Something went wrong.", + description: await result.text(), + }) + return + } - setGraph(Graph.empty()) + const json = await result.json() + const g = Graph.create(json.result.entities, graphName) + setGraph(g) - const result = await fetch(`/api/repo/${prepareArg(graphName)}`, { - method: 'GET' - }) + if (cooldownTicks === 0) setCooldownTicks(-1) - if (!result.ok) { + setIsPathResponse(false) + chatPanel.current?.expand() + // @ts-ignore + window.graph = g + } catch (error) { toast({ variant: "destructive", title: "Uh oh! Something went wrong.", - description: await result.text(), + description: "Failed to load repository graph. Please try again.", }) - return } - - const json = await result.json() - const g = Graph.create(json.result.entities, graphName) - setGraph(g) - - if (cooldownTicks === 0) setCooldownTicks(-1) - - setIsPathResponse(false) - chatPanel.current?.expand() - // @ts-ignore - window.graph = g } // Send the user query to the server to expand a node @@ -416,8 +421,9 @@ export default function Home() {
- + Date: Tue, 24 Feb 2026 11:49:22 +0200 Subject: [PATCH 159/189] Remove test.only from node path connection test to ensure all tests run --- e2e/tests/canvas.spec.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/e2e/tests/canvas.spec.ts b/e2e/tests/canvas.spec.ts index ef53a439..75e8c514 100644 --- a/e2e/tests/canvas.spec.ts +++ b/e2e/tests/canvas.spec.ts @@ -176,8 +176,7 @@ test.describe("Canvas tests", () => { }); nodesPath.forEach(({firstNode, secondNode}) => { - // BUG: canvas.getGraphData() returns stale data - isPath property not syncing after path selection - test.only(`Verify successful node path connection in canvas between ${firstNode} and ${secondNode} via UI`, async () => { + test(`Verify successful node path connection in canvas between ${firstNode} and ${secondNode} via UI`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPHRAG_SDK); await codeGraph.clickOnShowPathBtn("Show the path"); From 0d98edaf9a8877956fc255cf8e5a68e64bd51661 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Tue, 24 Feb 2026 11:51:23 +0200 Subject: [PATCH 160/189] Update graph data retrieval to use graphDesktop function for improved compatibility --- e2e/logic/POM/codeGraph.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 612b2d68..40de1472 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -590,7 +590,7 @@ export default class CodeGraph extends BasePage { await this.waitForCanvasAnimationToEnd(); // Wait for the graph data to be available on window object (set by handleEngineStop) await this.page.waitForFunction(() => { - const data = (window as any).graph?.(); + const data = (window as any).graphDesktop(); // Check both possible structures: { nodes } or { elements: { nodes } } return data && ((Array.isArray(data.nodes) && data.nodes.length > 0) || (data.elements && Array.isArray(data.elements.nodes) && data.elements.nodes.length > 0)); @@ -598,7 +598,7 @@ export default class CodeGraph extends BasePage { { timeout: 5000 }); const graphData = await this.page.evaluate(() => { - return (window as any).graph?.(); + return (window as any).graphDesktop(); }); let transformData: any = null; From 8462d3b56003875dd63ea4834afcc99ff4e481f8 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Tue, 24 Feb 2026 12:01:01 +0200 Subject: [PATCH 161/189] Fix canvas selection logic in handleDownloadImage for improved reliability --- app/page.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/page.tsx b/app/page.tsx index edc5b978..d755ea8b 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -269,8 +269,9 @@ export default function Home() { const handleDownloadImage = async () => { try { - const canvases = document.querySelectorAll('.force-graph-container canvas') as NodeListOf; - if (!canvases) { + const canvases = Array.from(document.querySelectorAll('falkordb-canvas').values()).map(canvas => canvas.shadowRoot?.querySelector('canvas')).filter((c): c is HTMLCanvasElement => !!c); + + if (canvases.length === 0) { toast({ title: "Error", description: "Canvas not found", From d764425b6c43590bd216c0a081dcad112dd37988 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Tue, 24 Feb 2026 12:23:27 +0200 Subject: [PATCH 162/189] Remove debug console logs from canvas tests for cleaner output --- e2e/tests/canvas.spec.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/e2e/tests/canvas.spec.ts b/e2e/tests/canvas.spec.ts index 75e8c514..7ca9cb18 100644 --- a/e2e/tests/canvas.spec.ts +++ b/e2e/tests/canvas.spec.ts @@ -105,17 +105,13 @@ test.describe("Canvas tests", () => { await codeGraph.insertInputForShowPath("2", path.secondNode); const initialGraph = await codeGraph.getGraphNodes(); const firstNode = findNodeByName(initialGraph, path.firstNode); - console.log("firstNode: ", firstNode); const secondNode = findNodeByName(initialGraph, path.secondNode); - console.log("secondNode: ", secondNode); expect(firstNode.isPath).toBe(true); expect(secondNode.isPath).toBe(true); await codeGraph.clickOnClearGraphBtn(); const updateGraph = await codeGraph.getGraphNodes(); const firstNode1 = findNodeByName(updateGraph, path.firstNode); const secondNode1 = findNodeByName(updateGraph, path.secondNode); - console.log("firstNode1: ", firstNode1); - console.log("secondNode1: ", secondNode1); expect(firstNode1.isPath).toBe(false); expect(secondNode1.isPath).toBe(false); }); @@ -184,12 +180,8 @@ test.describe("Canvas tests", () => { await codeGraph.insertInputForShowPath("2", secondNode); const result = await codeGraph.getGraphDetails(); const firstNodeRes = findNodeByName(result?.nodes, firstNode); - console.log("firstNodeRes: ", firstNodeRes); const secondnodeRes = findNodeByName(result?.nodes, secondNode); - console.log("secondNodeRes: ", secondnodeRes); - console.log("firstNodeRes: ", firstNodeRes.isPath); - console.log("secondnodeRes: ", secondnodeRes.isPath); expect(firstNodeRes).toBeDefined(); expect(secondnodeRes).toBeDefined(); From a2049969c1a0aec076f74ea21ed4811a614d6ddb Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Tue, 24 Feb 2026 12:24:33 +0200 Subject: [PATCH 163/189] Remove stale data bug comments from canvas tests for clarity --- e2e/tests/canvas.spec.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/e2e/tests/canvas.spec.ts b/e2e/tests/canvas.spec.ts index 7ca9cb18..eac29290 100644 --- a/e2e/tests/canvas.spec.ts +++ b/e2e/tests/canvas.spec.ts @@ -55,7 +55,6 @@ test.describe("Canvas tests", () => { }) - // BUG: canvas.getGraphData() returns stale data - visibility state not syncing after hide test(`Validate node hide functionality via element menu in canvas for ${nodes[0].nodeName}`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPHRAG_SDK); @@ -83,7 +82,6 @@ test.describe("Canvas tests", () => { categories.forEach((category, index) => { const checkboxIndex = index + 1; - // BUG: canvas.getGraphData() returns stale data - visibility state not syncing after checkbox uncheck test(`Verify that unchecking the ${category} checkbox hides ${category} nodes on the canvas`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPHRAG_SDK); @@ -95,7 +93,6 @@ test.describe("Canvas tests", () => { }) nodesPath.forEach((path) => { - // BUG: canvas.getGraphData() returns stale data - isPath property not syncing after path selection test(`Verify "Clear graph" button resets canvas view for path ${path.firstNode} and ${path.secondNode}`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await browser.setPageToFullScreen(); @@ -131,7 +128,6 @@ test.describe("Canvas tests", () => { for (let index = 0; index < 3; index++) { const nodeIndex: number = index + 1; - // BUG: canvas.getGraphData() returns stale data - node x/y positions not updating after drag test(`Validate canvas node dragging for node: ${index}`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPHRAG_SDK); @@ -213,7 +209,6 @@ test.describe("Canvas tests", () => { }); }) - // BUG: download button click does not trigger a file download test(`Verify file download is triggered and saved after clicking download`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPHRAG_SDK); From 80d7c4fe42dbce8b1d38adb4350a24a9c0a373c7 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Tue, 24 Feb 2026 12:54:44 +0200 Subject: [PATCH 164/189] Update Playwright imports to use @playwright/test and remove outdated dependencies --- e2e/infra/ui/basePage.ts | 2 +- e2e/infra/ui/browserWrapper.ts | 2 +- e2e/logic/POM/codeGraph.ts | 10 ++-- package-lock.json | 91 +++++++++++++++++----------------- package.json | 6 +-- 5 files changed, 56 insertions(+), 55 deletions(-) diff --git a/e2e/infra/ui/basePage.ts b/e2e/infra/ui/basePage.ts index 69baf604..b3aaa253 100644 --- a/e2e/infra/ui/basePage.ts +++ b/e2e/infra/ui/basePage.ts @@ -1,4 +1,4 @@ -import { Page } from 'playwright'; +import { Page } from '@playwright/test'; export default class BasePage { protected page: Page; diff --git a/e2e/infra/ui/browserWrapper.ts b/e2e/infra/ui/browserWrapper.ts index 985bf25c..77fa5d07 100644 --- a/e2e/infra/ui/browserWrapper.ts +++ b/e2e/infra/ui/browserWrapper.ts @@ -1,4 +1,4 @@ -import { chromium, Browser, BrowserContext, Page } from 'playwright'; +import { chromium, Browser, BrowserContext, Page } from '@playwright/test'; import BasePage from './basePage'; export default class BrowserWrapper { diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 40de1472..99b02355 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -1,4 +1,4 @@ -import { Download, Locator, Page } from "playwright"; +import { Download, Locator, Page } from "@playwright/test"; import BasePage from "../../infra/ui/basePage"; import { interactWhenVisible, waitForElementToBeVisible, waitForStableText, waitToBeEnabled } from "../utils"; @@ -499,10 +499,10 @@ export default class CodeGraph extends BasePage { await this.page.mouse.click(10, 10); await this.clearGraphBtn.click(); } - + async clickOnUnhideNodesBtn(): Promise { await interactWhenVisible( - this.unhideNodesBtn, (el) => el.click(),`Unhide Nodes Button` + this.unhideNodesBtn, (el) => el.click(), `Unhide Nodes Button` ); } @@ -593,7 +593,7 @@ export default class CodeGraph extends BasePage { const data = (window as any).graphDesktop(); // Check both possible structures: { nodes } or { elements: { nodes } } return data && ((Array.isArray(data.nodes) && data.nodes.length > 0) || - (data.elements && Array.isArray(data.elements.nodes) && data.elements.nodes.length > 0)); + (data.elements && Array.isArray(data.elements.nodes) && data.elements.nodes.length > 0)); }, { timeout: 5000 }); @@ -693,7 +693,7 @@ export default class CodeGraph extends BasePage { const data = (window as any).graph?.(); // Check both possible structures: { nodes } or { elements: { nodes } } return data && ((Array.isArray(data.nodes) && data.nodes.length > 0) || - (data.elements && Array.isArray(data.elements.nodes) && data.elements.nodes.length > 0)); + (data.elements && Array.isArray(data.elements.nodes) && data.elements.nodes.length > 0)); }, { timeout: 5000 }); const graphData = await this.page.evaluate(() => { diff --git a/package-lock.json b/package-lock.json index 691e885a..e6346077 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,7 +29,6 @@ "html2canvas": "^1.4.1", "lucide-react": "^0.486.0", "next": "^15.5.8", - "playwright": "^1.49.1", "react": "^18.3.1", "react-dom": "^18.3.1", "react-gtm-module": "^2.0.11", @@ -1080,6 +1079,52 @@ "node": ">=18" } }, + "node_modules/@playwright/test/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/@playwright/test/node_modules/playwright": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.57.0.tgz", + "integrity": "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.57.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/@playwright/test/node_modules/playwright-core": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.57.0.tgz", + "integrity": "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@radix-ui/number": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", @@ -6651,50 +6696,6 @@ "node": ">= 6" } }, - "node_modules/playwright": { - "version": "1.57.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.57.0.tgz", - "integrity": "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==", - "license": "Apache-2.0", - "dependencies": { - "playwright-core": "1.57.0" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "fsevents": "2.3.2" - } - }, - "node_modules/playwright-core": { - "version": "1.57.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.57.0.tgz", - "integrity": "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==", - "license": "Apache-2.0", - "bin": { - "playwright-core": "cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", diff --git a/package.json b/package.json index 40da1a8b..d75081f9 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "dev": "HOST=0.0.0.0 PORT=3000 next dev", "build": "next build", "start": "HOST=0.0.0.0 PORT=3000 next start", - "lint": "next lint" + "lint": "next lint", + "typecheck": "tsc --noEmit" }, "dependencies": { "@falkordb/canvas": "^0.0.37", @@ -30,7 +31,6 @@ "html2canvas": "^1.4.1", "lucide-react": "^0.486.0", "next": "^15.5.8", - "playwright": "^1.49.1", "react": "^18.3.1", "react-dom": "^18.3.1", "react-gtm-module": "^2.0.11", @@ -53,4 +53,4 @@ "tailwindcss": "^3.4.17", "typescript": "^5.7.3" } -} +} \ No newline at end of file From 40eba8f1f4ceaea37e27793918517f200c14bd12 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Tue, 24 Feb 2026 15:57:08 +0200 Subject: [PATCH 165/189] Enhance graph components with new link handling and update dependencies --- app/components/ForceGraph.tsx | 3 ++ app/components/chat.tsx | 87 +++++++++++++++++++++++++++++------ app/components/code-graph.tsx | 9 ++-- app/components/graphView.tsx | 81 +++++++++++++++++++++++--------- app/page.tsx | 8 ++-- package-lock.json | 8 ++-- package.json | 2 +- 7 files changed, 150 insertions(+), 48 deletions(-) diff --git a/app/components/ForceGraph.tsx b/app/components/ForceGraph.tsx index 6ba3196c..80c7f2fa 100644 --- a/app/components/ForceGraph.tsx +++ b/app/components/ForceGraph.tsx @@ -19,6 +19,7 @@ interface Props { nodePointerAreaPaint: (node: GraphNode, color: string, ctx: CanvasRenderingContext2D) => void linkCanvasObject: (link: any, ctx: CanvasRenderingContext2D) => void linkPointerAreaPaint: (link: any, color: string, ctx: CanvasRenderingContext2D) => void + linkLineDash: (link: any) => number[] | null onZoom: () => void onEngineStop: () => void cooldownTicks: number | undefined @@ -61,6 +62,7 @@ export default function ForceGraph({ nodePointerAreaPaint, linkCanvasObject, linkPointerAreaPaint, + linkLineDash, cooldownTicks, backgroundColor = "#FFFFFF", foregroundColor = "#000000" @@ -140,6 +142,7 @@ export default function ForceGraph({ onEngineStop: handleEngineStop, node: { nodeCanvasObject, nodePointerAreaPaint }, link: { linkCanvasObject, linkPointerAreaPaint }, + linkLineDash, onZoom }) }, [ diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 28107c75..ff99e169 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -9,7 +9,7 @@ import { cn, GraphRef } from "@/lib/utils"; import { TypeAnimation } from "react-type-animation"; import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; import { prepareArg } from "../utils"; -import { GraphNode } from "@falkordb/canvas"; +import { dataToGraphData, GraphLink, GraphNode } from "@falkordb/canvas"; interface Props { repo: string @@ -19,7 +19,6 @@ interface Props { selectedPathId: number | undefined isPathResponse: boolean | undefined setIsPathResponse: (isPathResponse: boolean | undefined) => void - setData: Dispatch> canvasRef: GraphRef messages: Message[] setMessages: Dispatch> @@ -27,6 +26,7 @@ interface Props { setQuery: Dispatch> selectedPath: PathData | undefined setSelectedPath: Dispatch> + setCooldownTicks: Dispatch> setChatOpen?: Dispatch> paths: PathData[] setPaths: Dispatch> @@ -52,7 +52,7 @@ const RemoveLastPath = (messages: Message[]) => { return messages } -export function Chat({ messages, setMessages, query, setQuery, selectedPath, setSelectedPath, setChatOpen, repo, path, setPath, graph, selectedPathId, isPathResponse, setIsPathResponse, setData, canvasRef, paths, setPaths }: Props) { +export function Chat({ messages, setMessages, query, setQuery, selectedPath, setSelectedPath, setChatOpen, repo, path, setPath, graph, selectedPathId, isPathResponse, setIsPathResponse, setCooldownTicks, canvasRef, paths, setPaths }: Props) { const [sugOpen, setSugOpen] = useState(false); @@ -273,27 +273,86 @@ export function Chat({ messages, setMessages, query, setQuery, selectedPath, set return } - const formattedPaths: PathData[] = json.result.paths.map((p: any) => ({ nodes: p.filter((n: any, i: number) => i % 2 === 0), links: p.filter((l: any, i: number) => i % 2 !== 0) })) - formattedPaths.forEach((p: any) => graph.extend(p, false, path)) - + const formattedPaths: PathData[] = json.result.paths.map((p: any) => ({ nodes: p.filter((_n: any, i: number) => i % 2 === 0), links: p.filter((l: any, i: number) => i % 2 !== 0) })) + const elements = formattedPaths.reduce( + (acc, p) => { + const el = graph.extend(p, false, path) + acc.nodes.push(...el.nodes) + acc.links.push(...el.links) + return acc + }, + { nodes: [], links: [] } + ) setPaths(formattedPaths) setMessages((prev) => [...prev.slice(0, -1), { type: MessageTypes.PathResponse, paths: formattedPaths, graphName: graph.Id }]); setIsPathResponse(true) const currentData = canvas.getGraphData(); - const nodesSet = new Set(formattedPaths.flatMap(p => p.nodes.map((n: Node) => n.id))); - const linksSet = new Set(formattedPaths.flatMap(p => p.links.map((l: any) => l.id))); + const nodesMap = new Map(currentData.nodes.map(n => [n.id, n])) + const linksMap = new Map(currentData.links.map(l => [l.id, l])) - currentData.nodes.forEach(n => { - n.data.isPath = nodesSet.has(n.id); + formattedPaths.flatMap(p => p.nodes).forEach(n => { + const node = nodesMap.get(n.id); + if (node) { + node.data.isPath = true; + } }); - currentData.links.forEach(l => { - l.data.isPath = linksSet.has(l.id); - l.color = linksSet.has(l.id) ? PATH_COLOR : l.color; + formattedPaths.flatMap(p => p.links).forEach(l => { + const link = linksMap.get(l.id); + + if (link) { + link.data.isPath = true; + link.color = PATH_COLOR; + } }); - canvas.setGraphData(currentData) + // Filter for only new elements + const newDataElements = { + nodes: elements.nodes.filter(n => !nodesMap.has(n.id)) + .map(({ category, color, data, id, isPath, isPathSelected, visible }) => ({ + color, + id, + labels: [category], + data: { + ...data, + isPath, + isPathSelected + }, + visible, + })), + links: elements.links.filter(l => !linksMap.has(l.id)) + .map(({ color, id, source, target, data, isPath, isPathSelected, visible, label }) => ({ + color: isPath ? PATH_COLOR : color, + id, + source, + target, + data: { + ...data, + isPath, + isPathSelected + }, + visible, + relationship: label, + })) + } + + // Convert only new data to GraphData format + const newGraphData = dataToGraphData( + newDataElements, + undefined, + new Map(currentData.nodes.map(n => [n.id, n])) + ) + + // Merge with existing data + canvasRef.current?.setGraphData({ + nodes: [...currentData.nodes, ...newGraphData.nodes], + links: [...currentData.links, ...newGraphData.links] + }) + + if (elements.nodes.length !== 0 || elements.links.length !== 0) { + setCooldownTicks(-1) + } setTimeout(() => { const nodesMap = new Map(formattedPaths.flatMap(p => p.nodes.map((n: Node) => [n.id, n]))) diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 0f591502..b75f9ef1 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -182,7 +182,7 @@ export function CodeGraph({ if (nodes.length === 0) return; const expandedNodes: Node[] = [] - const deleteIdsMap = new Map() + const deleteIdsMap = new Set() graph.Elements = { nodes: graph.Elements.nodes.filter(node => { @@ -192,7 +192,7 @@ export function CodeGraph({ if (!isTarget) return true - deleteIdsMap.set(node.id, true) + deleteIdsMap.add(node.id) const deleted = graph.NodesMap.delete(Number(node.id)) if (deleted && node.expand) { @@ -204,7 +204,7 @@ export function CodeGraph({ links: graph.Elements.links } - deleteNeighbors(expandedNodes) + deleteNeighbors(expandedNodes)?.forEach(id => deleteIdsMap.add(id)) graph.removeLinks() @@ -273,6 +273,8 @@ export function CodeGraph({ nodes: [...currentData.nodes, ...newGraphData.nodes], links: [...currentData.links, ...newGraphData.links] }) + + setCooldownTicks(-1) } else { const deleteNodes = nodes.filter(n => n.expand) if (deleteNodes.length > 0) { @@ -287,6 +289,7 @@ export function CodeGraph({ currentData.links = currentData.links.filter(link => !deleteIdsMap.has(Number(link.source.id)) && !deleteIdsMap.has(Number(link.target.id))) canvasRef.current?.setGraphData(currentData) + setCooldownTicks(-1) } } } diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 4c20b3b4..2554e96b 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -24,7 +24,7 @@ interface Props { selectedObjects: Node[] setSelectedObjects: Dispatch> setPosition: Dispatch> - handleExpand: (nodes: Node[], expand: boolean) => void + handleExpand: (nodes: Node[], expand: boolean) => void isShowPath: boolean setPath: Dispatch> isPathResponse: boolean | undefined @@ -207,7 +207,7 @@ export default function GraphView({ ctx.fillStyle = color; ctx.beginPath(); - ctx.arc(node.x, node.y, NODE_SIZE + 4 + ctx.lineWidth / 2, 0, 2 * Math.PI, false); + ctx.arc(node.x, node.y, NODE_SIZE + 2 + ctx.lineWidth / 2, 0, 2 * Math.PI, false); ctx.fill(); }, []) @@ -222,6 +222,9 @@ export default function GraphView({ const even = index % 2 === 0 let curve + ctx.strokeStyle = '#999999'; + ctx.lineWidth = 0.1; + if (start.id === end.id) { if (even) { curve = Math.floor(-(index / 2)) - 3 @@ -231,14 +234,25 @@ export default function GraphView({ link.curve = curve * 0.1 - const radius = NODE_SIZE * link.curve * 6.2; - const angleOffset = -Math.PI / 4; // 45 degrees offset for text alignment - const textX = start.x + radius * Math.cos(angleOffset); - const textY = start.y + radius * Math.sin(angleOffset); + const d = link.curve * 70; + + ctx.beginPath(); + ctx.moveTo(start.x, start.y); + ctx.bezierCurveTo(start.x, start.y - d, start.x + d, start.y, start.x, start.y); + ctx.stroke(); + + // Midpoint of cubic bezier: P0=(sx,sy), P1=(sx,sy-d), P2=(sx+d,sy), P3=(sx,sy) + const textX = start.x + 0.375 * d; + const textY = start.y - 0.375 * d; + + // Tangent at midpoint is (0.75d, 0.75d), angle always resolves to PI/4 + let textAngle = Math.atan2(0.75 * d, 0.75 * d); + if (textAngle > Math.PI / 2) textAngle = -(Math.PI - textAngle); + if (textAngle < -Math.PI / 2) textAngle = -(-Math.PI - textAngle); ctx.save(); ctx.translate(textX, textY); - ctx.rotate(-angleOffset); + ctx.rotate(textAngle); } else { if (even) { curve = Math.floor(-(index / 2)) @@ -248,8 +262,23 @@ export default function GraphView({ link.curve = curve * 0.1 - const midX = (start.x + end.x) / 2 + (end.y - start.y) * (link.curve / 2); - const midY = (start.y + end.y) / 2 + (start.x - end.x) * (link.curve / 2); + const dx = end.x - start.x; + const dy = end.y - start.y; + const dist = Math.sqrt(dx * dx + dy * dy); + const curvature = link.curve; + const cpX = (start.x + end.x) / 2 + (dy / dist) * curvature * dist; + const cpY = (start.y + end.y) / 2 + (-dx / dist) * curvature * dist; + + // Draw the quadratic bezier curve + ctx.beginPath(); + ctx.moveTo(start.x, start.y); + ctx.quadraticCurveTo(cpX, cpY, end.x, end.y); + ctx.stroke(); + + // Midpoint of quadratic bezier at t=0.5 + const t = 0.5; + const midX = (1 - t) * (1 - t) * start.x + 2 * (1 - t) * t * cpX + t * t * end.x; + const midY = (1 - t) * (1 - t) * start.y + 2 * (1 - t) * t * cpY + t * t * end.y; let textAngle = Math.atan2(end.y - start.y, end.x - start.x) @@ -272,22 +301,26 @@ export default function GraphView({ ctx.restore() }, [graph.Elements.links]) + const linkLineDash = useCallback((link: GraphLink) => { + if (link.data.isPath && !link.data.isPathSelected) return [5, 5] + return null + }, []) + const linkPointerAreaPaint = useCallback((link: GraphLink, color: string, ctx: CanvasRenderingContext2D) => { const start = link.source; const end = link.target; if (!start.x || !start.y || !end.x || !end.y) return - ctx.fillStyle = color; + ctx.strokeStyle = color; + ctx.lineWidth = 1; - // Calculate curve the same way as linkCanvasObject const sameNodesLinks = graph.Elements.links.filter(l => (l.source === start.id && l.target === end.id) || (l.target === start.id && l.source === end.id)) const index = sameNodesLinks.findIndex(l => l.id === link.id) || 0 const even = index % 2 === 0 let curve if (start.id === end.id) { - // Self-loop: draw clickable area at the loop position if (even) { curve = Math.floor(-(index / 2)) - 3 } else { @@ -295,16 +328,13 @@ export default function GraphView({ } const curvature = curve * 0.1 - const radius = NODE_SIZE * curvature * 6.2; - const angleOffset = -Math.PI / 4; - const textX = start.x + radius * Math.cos(angleOffset); - const textY = start.y + radius * Math.sin(angleOffset); + const d = curvature * 70; ctx.beginPath(); - ctx.arc(textX, textY, 5, 0, 2 * Math.PI, false); - ctx.fill(); + ctx.moveTo(start.x, start.y); + ctx.bezierCurveTo(start.x, start.y - d, start.x + d, start.y, start.x, start.y); + ctx.stroke(); } else { - // Regular link: draw clickable area at the curve midpoint if (even) { curve = Math.floor(-(index / 2)) } else { @@ -312,12 +342,16 @@ export default function GraphView({ } const curvature = curve * 0.1 - const midX = (start.x + end.x) / 2 + (end.y - start.y) * (curvature / 2); - const midY = (start.y + end.y) / 2 + (start.x - end.x) * (curvature / 2); + const dx = end.x - start.x; + const dy = end.y - start.y; + const dist = Math.sqrt(dx * dx + dy * dy); + const cpX = (start.x + end.x) / 2 + (dy / dist) * curvature * dist; + const cpY = (start.y + end.y) / 2 + (-dx / dist) * curvature * dist; ctx.beginPath(); - ctx.arc(midX, midY, 5, 0, 2 * Math.PI, false); - ctx.fill(); + ctx.moveTo(start.x, start.y); + ctx.quadraticCurveTo(cpX, cpY, end.x, end.y); + ctx.stroke(); } }, [graph.Elements.links]) @@ -344,6 +378,7 @@ export default function GraphView({ nodePointerAreaPaint={nodePointerAreaPaint} linkCanvasObject={linkCanvasObject} linkPointerAreaPaint={linkPointerAreaPaint} + linkLineDash={linkLineDash} cooldownTicks={cooldownTicks} />
diff --git a/app/page.tsx b/app/page.tsx index d755ea8b..7739e5a4 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,7 +1,6 @@ 'use client' import { useEffect, useRef, useState } from 'react'; -import { Chat } from './components/chat'; import { Graph, GraphData, Node } from './components/model'; import { AlignRight, BookOpen, BoomBox, Download, Github, HomeIcon, Search, X } from 'lucide-react'; import Link from 'next/link'; @@ -22,6 +21,7 @@ import { cn, GraphRef, Message, Path, PathData, PathNode } from '@/lib/utils'; import type { GraphNode } from '@falkordb/canvas'; import dynamic from 'next/dynamic'; +const Chat = dynamic(() => import('./components/chat').then(mod => mod.Chat), { ssr: false }); const CodeGraph = dynamic(() => import('./components/code-graph').then(mod => mod.CodeGraph), { ssr: false }); type Tip = { @@ -203,6 +203,8 @@ export default function Home() { const handleSearchSubmit = (node: any, canvasRef: GraphRef) => { const canvas = canvasRef.current + debugger + if (canvas) { let chartNode = graph.Elements.nodes.find(n => n.id == node.id) @@ -477,9 +479,9 @@ export default function Home() { selectedPathId={selectedPathId} isPathResponse={isPathResponse} setIsPathResponse={setIsPathResponse} - setData={setData} paths={paths} setPaths={setPaths} + setCooldownTicks={setCooldownTicks} /> @@ -601,10 +603,10 @@ export default function Home() { selectedPathId={selectedPathId} isPathResponse={isPathResponse} setIsPathResponse={setIsPathResponse} - setData={setData} setChatOpen={setChatOpen} paths={paths} setPaths={setPaths} + setCooldownTicks={setCooldownTicks} /> diff --git a/package-lock.json b/package-lock.json index e6346077..d3260c9f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "code-graph", "version": "0.2.0", "dependencies": { - "@falkordb/canvas": "^0.0.37", + "@falkordb/canvas": "^0.0.38", "@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dropdown-menu": "^2.1.6", @@ -251,9 +251,9 @@ } }, "node_modules/@falkordb/canvas": { - "version": "0.0.37", - "resolved": "https://registry.npmjs.org/@falkordb/canvas/-/canvas-0.0.37.tgz", - "integrity": "sha512-/y4omfjh0GdXp2M5QqPS2OyU8dPHndSCfYq4MbgvjoKvRRAVX4TLcmNMsRELXZX4+18QT7yi4vUbKgG4SEMyNA==", + "version": "0.0.38", + "resolved": "https://registry.npmjs.org/@falkordb/canvas/-/canvas-0.0.38.tgz", + "integrity": "sha512-Lxsn0S+zG4AO5hRpgaPfsWw4QgeO+ifEY47utZxcTnMjtiI4nUH6sBzpONz8xhNXU7RWywjYaT+jzjb1PIPyGQ==", "license": "MIT", "dependencies": { "d3": "^7.9.0", diff --git a/package.json b/package.json index d75081f9..a9aeeea8 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@falkordb/canvas": "^0.0.37", + "@falkordb/canvas": "^0.0.38", "@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dropdown-menu": "^2.1.6", From 11e1630b9e1e27362badee2dfa4ddd3cb7c26c6d Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Tue, 24 Feb 2026 16:32:42 +0200 Subject: [PATCH 166/189] Refactor link curvature calculation in GraphView for improved scaling --- app/components/graphView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 2554e96b..63606835 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -234,7 +234,7 @@ export default function GraphView({ link.curve = curve * 0.1 - const d = link.curve * 70; + const d = link.curve * NODE_SIZE * 11.67; ctx.beginPath(); ctx.moveTo(start.x, start.y); @@ -328,7 +328,7 @@ export default function GraphView({ } const curvature = curve * 0.1 - const d = curvature * 70; + const d = curvature * NODE_SIZE * 11.67; ctx.beginPath(); ctx.moveTo(start.x, start.y); From 5d7ecba4f9cf8f1042ec5d78aff6a197d6dc0909 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Wed, 25 Feb 2026 16:01:32 +0200 Subject: [PATCH 167/189] Update @falkordb/canvas to version 0.0.40 and refactor graph component handlers for improved link and node interactions --- app/components/ForceGraph.tsx | 61 ++++++++++-- app/components/graphView.tsx | 181 +++++++-------------------------- app/page.tsx | 60 +++++++++-- package-lock.json | 183 ++++------------------------------ package.json | 2 +- 5 files changed, 162 insertions(+), 325 deletions(-) diff --git a/app/components/ForceGraph.tsx b/app/components/ForceGraph.tsx index 80c7f2fa..decb57f3 100644 --- a/app/components/ForceGraph.tsx +++ b/app/components/ForceGraph.tsx @@ -1,7 +1,7 @@ "use client" import { useCallback, useEffect, useState } from "react" -import type { Data, GraphNode } from "@falkordb/canvas" +import type { Data, GraphLink, GraphNode } from "@falkordb/canvas" import { GraphRef, PATH_COLOR } from "@/lib/utils" import { GraphData, Link, Node } from "./model" @@ -10,15 +10,17 @@ interface Props { data: GraphData canvasRef: GraphRef onNodeClick: (node: Node, event: MouseEvent) => void + onNodeHover: (node: Node | null) => void onNodeRightClick: (node: Node, event: MouseEvent) => void + isNodeSelected: (node: GraphNode) => boolean onLinkClick: (link: Link, event: MouseEvent) => void + onLinkHover: (link: Link | null) => void onLinkRightClick: (link: Link, event: MouseEvent) => void + isLinkSelected: (link: GraphLink) => boolean onBackgroundClick: (event: MouseEvent) => void onBackgroundRightClick: (event: MouseEvent) => void nodeCanvasObject: (node: GraphNode, ctx: CanvasRenderingContext2D) => void nodePointerAreaPaint: (node: GraphNode, color: string, ctx: CanvasRenderingContext2D) => void - linkCanvasObject: (link: any, ctx: CanvasRenderingContext2D) => void - linkPointerAreaPaint: (link: any, color: string, ctx: CanvasRenderingContext2D) => void linkLineDash: (link: any) => number[] | null onZoom: () => void onEngineStop: () => void @@ -51,17 +53,19 @@ export default function ForceGraph({ data, canvasRef, onNodeClick, + onNodeHover, onNodeRightClick, + isNodeSelected, onLinkClick, + onLinkHover, onLinkRightClick, + isLinkSelected, onBackgroundClick, onBackgroundRightClick, onZoom, onEngineStop, nodeCanvasObject, nodePointerAreaPaint, - linkCanvasObject, - linkPointerAreaPaint, linkLineDash, cooldownTicks, backgroundColor = "#FFFFFF", @@ -99,25 +103,49 @@ export default function ForceGraph({ }, [canvasRef, cooldownTicks, canvasLoaded]) // Map node click handler - const handleNodeClick = useCallback((node: any, event: MouseEvent) => { + const handleNodeClick = useCallback((node: GraphNode, event: MouseEvent) => { const originalNode = data.nodes.find(n => n.id === node.id) if (originalNode) onNodeClick(originalNode, event) }, [onNodeClick, data.nodes]) + // Map node hover handler + const handleNodeHover = useCallback((node: GraphNode | null) => { + if (!node) { + onNodeHover(null) + return + } + + const originalNode = data.nodes.find(n => n.id === node.id) + + if (originalNode) onNodeHover(originalNode) + }, [onNodeHover, data.nodes]) + // Map node right click handler - const handleNodeRightClick = useCallback((node: any, event: MouseEvent) => { + const handleNodeRightClick = useCallback((node: GraphNode, event: MouseEvent) => { const originalNode = data.nodes.find(n => n.id === node.id) if (originalNode) onNodeRightClick(originalNode, event) }, [onNodeRightClick, data.nodes]) // Map link click handler - const handleLinkClick = useCallback((link: any, event: MouseEvent) => { + const handleLinkClick = useCallback((link: GraphLink, event: MouseEvent) => { const originalLink = data.links.find(l => l.id === link.id) if (originalLink) onLinkClick(originalLink, event) }, [onLinkClick, data.links]) + // Map link hover handler + const handleLinkHover = useCallback((link: GraphLink | null) => { + if (!link) { + onLinkHover(null) + return + } + + const originalLink = data.links.find(l => l.id === link.id) + + if (originalLink) onLinkHover(originalLink) + }, [onLinkHover, data.links]) + // Map link right click handler - const handleLinkRightClick = useCallback((link: any, event: MouseEvent) => { + const handleLinkRightClick = useCallback((link: GraphLink, event: MouseEvent) => { const originalLink = data.links.find(l => l.id === link.id) if (originalLink) onLinkRightClick(originalLink, event) }, [onLinkRightClick, data.links]) @@ -132,27 +160,38 @@ export default function ForceGraph({ if (!canvasRef.current || !canvasLoaded) return canvasRef.current.setConfig({ autoStopOnSettle: false, + // nodes will display node.data.captionsKeys in the canvas captionsKeys: ["name", "title"], onNodeClick: handleNodeClick, onNodeRightClick: handleNodeRightClick, + onNodeHover: handleNodeHover, + isNodeSelected: isNodeSelected, onLinkClick: handleLinkClick, onLinkRightClick: handleLinkRightClick, + onLinkHover: handleLinkHover, + isLinkSelected: isLinkSelected, onBackgroundClick, onBackgroundRightClick, onEngineStop: handleEngineStop, node: { nodeCanvasObject, nodePointerAreaPaint }, - link: { linkCanvasObject, linkPointerAreaPaint }, linkLineDash, onZoom }) }, [ handleNodeClick, handleNodeRightClick, + handleNodeHover, handleLinkClick, handleLinkRightClick, + handleLinkHover, + isNodeSelected, + isLinkSelected, onBackgroundClick, onBackgroundRightClick, handleEngineStop, + nodeCanvasObject, + nodePointerAreaPaint, + linkLineDash, onZoom, canvasRef, canvasLoaded @@ -168,6 +207,6 @@ export default function ForceGraph({ }, [canvasRef, data, canvasLoaded]) return ( - + ) } diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 63606835..aefda794 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -63,6 +63,7 @@ export default function GraphView({ const lastClick = useRef<{ date: Date, name: string }>({ date: new Date(), name: "" }) const [screenSize, setScreenSize] = useState(0) + const [hoverElement, setHoverElement] = useState() useEffect(() => { const handleResize = () => { @@ -106,6 +107,30 @@ export default function GraphView({ setSelectedPathId(link.id) } + const handleNodeHover = useCallback((node: Node | null) => { + setHoverElement(node) + }, []) + + const handleLinkHover = useCallback((link: Link | null) => { + setHoverElement(link) + }, []) + + const isNodeSelected = useCallback((node: GraphNode) => { + if (isPathResponse) { + return node.data.isPathSelected + } else { + return selectedObjects.some(obj => "category" in obj && obj.id === node.id) || (selectedObj && "category" in selectedObj && selectedObj?.id === node.id) || (hoverElement && ('category' in hoverElement) && hoverElement.id === node.id) + } + }, [isPathResponse, selectedObjects, selectedObj, hoverElement]) + + const isLinkSelected = useCallback((link: GraphLink) => { + if (isPathResponse) { + return link.data.isPathSelected + } else { + return selectedObjects.some(obj => "source" in obj && obj.id === link.id) || (selectedObj && "source" in selectedObj && selectedObj?.id === link.id) || (hoverElement && 'source' in hoverElement && hoverElement.id === link.id) + } + }, [isPathResponse, selectedObjects, selectedObj, hoverElement]) + const handleNodeClick = useCallback(async (node: Node) => { const now = new Date() const { date, name } = lastClick.current @@ -141,6 +166,9 @@ export default function GraphView({ const nodeCanvasObject = useCallback((node: GraphNode, ctx: CanvasRenderingContext2D) => { if (!node.x || !node.y) return + const isHovered = !!hoverElement && !('source' in hoverElement) && hoverElement.id === node.id + const isSelected = selectedObjects.some(obj => obj.id === node.id) || selectedObj?.id === node.id + if (isPathResponse) { if (node.data.isPathSelected) { ctx.fillStyle = node.color; @@ -167,12 +195,12 @@ export default function GraphView({ } else { ctx.fillStyle = node.color; ctx.strokeStyle = 'black'; - ctx.lineWidth = selectedObjects.some(obj => obj.id === node.id) || selectedObj?.id === node.id ? 1.5 : 1 + ctx.lineWidth = isSelected || isHovered ? 1.5 : 1 } } else { ctx.fillStyle = node.color; ctx.strokeStyle = 'black'; - ctx.lineWidth = selectedObjects.some(obj => obj.id === node.id) || selectedObj?.id === node.id ? 1.5 : 1 + ctx.lineWidth = isSelected || isHovered ? 1.5 : 1 } ctx.beginPath(); @@ -183,7 +211,7 @@ export default function GraphView({ ctx.fillStyle = 'black'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; - ctx.font = '4px Arial'; + ctx.font = '2px Arial'; let name = node.data.name || ""; const textWidth = ctx.measureText(name).width; const ellipsis = '...'; @@ -200,7 +228,7 @@ export default function GraphView({ // add label ctx.fillText(name, node.x, node.y); - }, [selectedObj, selectedObjects, isPathResponse]) + }, [selectedObj, selectedObjects, isPathResponse, hoverElement]) const nodePointerAreaPaint = useCallback((node: GraphNode, color: string, ctx: CanvasRenderingContext2D) => { if (!node.x || !node.y) return @@ -211,150 +239,11 @@ export default function GraphView({ ctx.fill(); }, []) - const linkCanvasObject = useCallback((link: GraphLink, ctx: CanvasRenderingContext2D) => { - const start = link.source; - const end = link.target; - - if (!start.x || !start.y || !end.x || !end.y) return - - const sameNodesLinks = graph.Elements.links.filter(l => (l.source === start.id && l.target === end.id) || (l.target === start.id && l.source === end.id)) - const index = sameNodesLinks.findIndex(l => l.id === link.id) || 0 - const even = index % 2 === 0 - let curve - - ctx.strokeStyle = '#999999'; - ctx.lineWidth = 0.1; - - if (start.id === end.id) { - if (even) { - curve = Math.floor(-(index / 2)) - 3 - } else { - curve = Math.floor((index + 1) / 2) + 2 - } - - link.curve = curve * 0.1 - - const d = link.curve * NODE_SIZE * 11.67; - - ctx.beginPath(); - ctx.moveTo(start.x, start.y); - ctx.bezierCurveTo(start.x, start.y - d, start.x + d, start.y, start.x, start.y); - ctx.stroke(); - - // Midpoint of cubic bezier: P0=(sx,sy), P1=(sx,sy-d), P2=(sx+d,sy), P3=(sx,sy) - const textX = start.x + 0.375 * d; - const textY = start.y - 0.375 * d; - - // Tangent at midpoint is (0.75d, 0.75d), angle always resolves to PI/4 - let textAngle = Math.atan2(0.75 * d, 0.75 * d); - if (textAngle > Math.PI / 2) textAngle = -(Math.PI - textAngle); - if (textAngle < -Math.PI / 2) textAngle = -(-Math.PI - textAngle); - - ctx.save(); - ctx.translate(textX, textY); - ctx.rotate(textAngle); - } else { - if (even) { - curve = Math.floor(-(index / 2)) - } else { - curve = Math.floor((index + 1) / 2) - } - - link.curve = curve * 0.1 - - const dx = end.x - start.x; - const dy = end.y - start.y; - const dist = Math.sqrt(dx * dx + dy * dy); - const curvature = link.curve; - const cpX = (start.x + end.x) / 2 + (dy / dist) * curvature * dist; - const cpY = (start.y + end.y) / 2 + (-dx / dist) * curvature * dist; - - // Draw the quadratic bezier curve - ctx.beginPath(); - ctx.moveTo(start.x, start.y); - ctx.quadraticCurveTo(cpX, cpY, end.x, end.y); - ctx.stroke(); - - // Midpoint of quadratic bezier at t=0.5 - const t = 0.5; - const midX = (1 - t) * (1 - t) * start.x + 2 * (1 - t) * t * cpX + t * t * end.x; - const midY = (1 - t) * (1 - t) * start.y + 2 * (1 - t) * t * cpY + t * t * end.y; - - let textAngle = Math.atan2(end.y - start.y, end.x - start.x) - - // maintain label vertical orientation for legibility - if (textAngle > Math.PI / 2) textAngle = -(Math.PI - textAngle); - if (textAngle < -Math.PI / 2) textAngle = -(-Math.PI - textAngle); - - ctx.save(); - ctx.translate(midX, midY); - ctx.rotate(textAngle); - } - - // add label - ctx.globalAlpha = 1; - ctx.fillStyle = 'black'; - ctx.textAlign = 'center'; - ctx.textBaseline = 'middle'; - ctx.font = '2px Arial'; - ctx.fillText(link.relationship, 0, 0); - ctx.restore() - }, [graph.Elements.links]) - const linkLineDash = useCallback((link: GraphLink) => { if (link.data.isPath && !link.data.isPathSelected) return [5, 5] return null }, []) - const linkPointerAreaPaint = useCallback((link: GraphLink, color: string, ctx: CanvasRenderingContext2D) => { - const start = link.source; - const end = link.target; - - if (!start.x || !start.y || !end.x || !end.y) return - - ctx.strokeStyle = color; - ctx.lineWidth = 1; - - const sameNodesLinks = graph.Elements.links.filter(l => (l.source === start.id && l.target === end.id) || (l.target === start.id && l.source === end.id)) - const index = sameNodesLinks.findIndex(l => l.id === link.id) || 0 - const even = index % 2 === 0 - let curve - - if (start.id === end.id) { - if (even) { - curve = Math.floor(-(index / 2)) - 3 - } else { - curve = Math.floor((index + 1) / 2) + 2 - } - - const curvature = curve * 0.1 - const d = curvature * NODE_SIZE * 11.67; - - ctx.beginPath(); - ctx.moveTo(start.x, start.y); - ctx.bezierCurveTo(start.x, start.y - d, start.x + d, start.y, start.x, start.y); - ctx.stroke(); - } else { - if (even) { - curve = Math.floor(-(index / 2)) - } else { - curve = Math.floor((index + 1) / 2) - } - - const curvature = curve * 0.1 - const dx = end.x - start.x; - const dy = end.y - start.y; - const dist = Math.sqrt(dx * dx + dy * dy); - const cpX = (start.x + end.x) / 2 + (dy / dist) * curvature * dist; - const cpY = (start.y + end.y) / 2 + (-dx / dist) * curvature * dist; - - ctx.beginPath(); - ctx.moveTo(start.x, start.y); - ctx.quadraticCurveTo(cpX, cpY, end.x, end.y); - ctx.stroke(); - } - }, [graph.Elements.links]) - return (
@@ -367,17 +256,19 @@ export default function GraphView({ data={data} canvasRef={canvasRef} onNodeClick={screenSize > Number(process.env.NEXT_PUBLIC_MOBILE_BREAKPOINT) || isShowPath ? (node: Node, _evt: MouseEvent) => handleNodeClick(node) : (node: Node, evt: MouseEvent) => handleRightClick(node, evt)} + onNodeHover={handleNodeHover} onNodeRightClick={handleRightClick} + isNodeSelected={isNodeSelected} onLinkClick={screenSize > Number(process.env.NEXT_PUBLIC_MOBILE_BREAKPOINT) && isPathResponse ? handleLinkClick : handleRightClick} + onLinkHover={handleLinkHover} onLinkRightClick={handleRightClick} + isLinkSelected={isLinkSelected} onBackgroundClick={unsetSelectedObjects} onBackgroundRightClick={unsetSelectedObjects} onZoom={() => unsetSelectedObjects()} onEngineStop={handleEngineStop} nodeCanvasObject={nodeCanvasObject} nodePointerAreaPaint={nodePointerAreaPaint} - linkCanvasObject={linkCanvasObject} - linkPointerAreaPaint={linkPointerAreaPaint} linkLineDash={linkLineDash} cooldownTicks={cooldownTicks} /> diff --git a/app/page.tsx b/app/page.tsx index 7739e5a4..f8f465c5 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -200,11 +200,9 @@ export default function Home() { return graph.extend(json.result.neighbors, true) } - const handleSearchSubmit = (node: any, canvasRef: GraphRef) => { + const handleSearchSubmit = async (node: any, canvasRef: GraphRef) => { const canvas = canvasRef.current - debugger - if (canvas) { let chartNode = graph.Elements.nodes.find(n => n.id == node.id) @@ -216,11 +214,58 @@ export default function Home() { setZoomedNodes([chartNode]) graph.visibleLinks(true, [chartNode!.id]) - setData({ ...graph.Elements }) + + const currentData = canvas.getGraphData() + + const { dataToGraphData } = await import('@falkordb/canvas') + const graphNode = dataToGraphData({ + nodes: [{ + color: chartNode.color, + id: chartNode.id, + labels: [chartNode.category], + visible: chartNode.visible, + data: { + ...chartNode.data, + isPath: chartNode.isPath, + isPathSelected: chartNode.isPathSelected, + } + }], links: [] + }).nodes[0] + + if (graphNode) { + currentData.nodes.push(graphNode) + } + + canvas.setGraphData(currentData) + + + setTimeout(() => { + canvas.zoomToFit(4, (n: GraphNode) => n.id === chartNode!.id) + }, 0) + setSearchNode(chartNode) + setOptionsOpen(false) + return } + chartNode.visible = true graph.visibleLinks(true, [chartNode!.id]) - setData({ ...graph.Elements }) + + const currentData = canvas.getGraphData() + + const graphNode = currentData.nodes.find(n => n.id === chartNode!.id) + if (graphNode) { + graphNode.visible = true + } + + currentData.links.forEach(canvasLink => { + const appLink = graph.LinksMap.get(canvasLink.id) + + if (appLink) { + canvasLink.visible = appLink.visible + } + }) + + canvas.setGraphData(currentData) } setTimeout(() => { @@ -240,7 +285,7 @@ export default function Home() { graph.Categories.find(c => c.name === name)!.show = show graph.Elements.nodes.forEach(node => { - if (!(node.category === name)) return + if (node.category !== name) return node.visible = show }) @@ -255,6 +300,7 @@ export default function Home() { canvasNode.visible = appNode.visible; } }); + currentData.links.forEach(canvasLink => { const appLink = graph.LinksMap.get(canvasLink.id); @@ -272,7 +318,7 @@ export default function Home() { const handleDownloadImage = async () => { try { const canvases = Array.from(document.querySelectorAll('falkordb-canvas').values()).map(canvas => canvas.shadowRoot?.querySelector('canvas')).filter((c): c is HTMLCanvasElement => !!c); - + if (canvases.length === 0) { toast({ title: "Error", diff --git a/package-lock.json b/package-lock.json index d3260c9f..52f8d36d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "code-graph", "version": "0.2.0", "dependencies": { - "@falkordb/canvas": "^0.0.38", + "@falkordb/canvas": "v0.0.40", "@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dropdown-menu": "^2.1.6", @@ -52,6 +52,25 @@ "typescript": "^5.7.3" } }, + "../falkordb-canvas": { + "name": "@falkordb/canvas", + "version": "0.0.40", + "license": "MIT", + "dependencies": { + "d3": "^7.9.0", + "force-graph": "^1.44.4", + "react": "^19.2.3" + }, + "devDependencies": { + "@types/d3": "^7.4.3", + "@types/react": "^19.2.7", + "@typescript-eslint/eslint-plugin": "^8.18.2", + "@typescript-eslint/parser": "^8.18.2", + "eslint": "^9.17.0", + "tsup": "^8.5.1", + "typescript": "^5.9.3" + } + }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", @@ -251,24 +270,8 @@ } }, "node_modules/@falkordb/canvas": { - "version": "0.0.38", - "resolved": "https://registry.npmjs.org/@falkordb/canvas/-/canvas-0.0.38.tgz", - "integrity": "sha512-Lxsn0S+zG4AO5hRpgaPfsWw4QgeO+ifEY47utZxcTnMjtiI4nUH6sBzpONz8xhNXU7RWywjYaT+jzjb1PIPyGQ==", - "license": "MIT", - "dependencies": { - "d3": "^7.9.0", - "force-graph": "^1.44.4", - "react": "^19.2.3" - } - }, - "node_modules/@falkordb/canvas/node_modules/react": { - "version": "19.2.3", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", - "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } + "resolved": "../falkordb-canvas", + "link": true }, "node_modules/@floating-ui/core": { "version": "1.7.3", @@ -2132,12 +2135,6 @@ "tslib": "^2.8.0" } }, - "node_modules/@tweenjs/tween.js": { - "version": "25.0.0", - "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-25.0.0.tgz", - "integrity": "sha512-XKLA6syeBUaPzx4j3qwMqzzq+V4uo72BnlbOjmuljLrRqdsd3qnzvZZoxvMHZ23ndsRS4aufU6JOZYpCbU6T1A==", - "license": "MIT" - }, "node_modules/@tybys/wasm-util": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", @@ -2768,15 +2765,6 @@ "win32" ] }, - "node_modules/accessor-fn": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/accessor-fn/-/accessor-fn-1.5.3.tgz", - "integrity": "sha512-rkAofCwe/FvYFUlMB0v0gWmhqtfAtV1IUkdPbfhTUyYniu5LrC0A0UJkTH0Jv3S8SvwkmfuAlY+mQIJATdocMA==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", @@ -3161,16 +3149,6 @@ "baseline-browser-mapping": "dist/cli.js" } }, - "node_modules/bezier-js": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/bezier-js/-/bezier-js-6.1.4.tgz", - "integrity": "sha512-PA0FW9ZpcHbojUCMu28z9Vg/fNkwTj5YhusSAjHHDfHDGLxJ6YUKrAN2vk1fP2MMOxVw4Oko16FMlRGVBGqLKg==", - "license": "MIT", - "funding": { - "type": "individual", - "url": "https://github.com/Pomax/bezierjs/blob/master/FUNDING.md" - } - }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -3328,18 +3306,6 @@ ], "license": "CC-BY-4.0" }, - "node_modules/canvas-color-tracker": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/canvas-color-tracker/-/canvas-color-tracker-1.3.2.tgz", - "integrity": "sha512-ryQkDX26yJ3CXzb3hxUVNlg1NKE4REc5crLBq661Nxzr8TNd236SaEf2ffYLXyI5tSABSeguHLqcVq4vf9L3Zg==", - "license": "MIT", - "dependencies": { - "tinycolor2": "^1.6.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/canvas2svg": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/canvas2svg/-/canvas2svg-1.0.16.tgz", @@ -3627,12 +3593,6 @@ "node": ">=12" } }, - "node_modules/d3-binarytree": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-binarytree/-/d3-binarytree-1.0.2.tgz", - "integrity": "sha512-cElUNH+sHu95L04m92pG73t2MEJXKu+GeKUN1TJkFsu93E5W8E9Sc3kHEGJKgenGvj19m6upSn2EunvMgMD2Yw==", - "license": "MIT" - }, "node_modules/d3-brush": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", @@ -3776,22 +3736,6 @@ "node": ">=12" } }, - "node_modules/d3-force-3d": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/d3-force-3d/-/d3-force-3d-3.0.6.tgz", - "integrity": "sha512-4tsKHUPLOVkyfEffZo1v6sFHvGFwAIIjt/W8IThbp08DYAsXZck+2pSHEG5W1+gQgEvFLdZkYvmJAbRM2EzMnA==", - "license": "MIT", - "dependencies": { - "d3-binarytree": "1", - "d3-dispatch": "1 - 3", - "d3-octree": "1", - "d3-quadtree": "1 - 3", - "d3-timer": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/d3-format": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", @@ -3834,12 +3778,6 @@ "node": ">=12" } }, - "node_modules/d3-octree": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-octree/-/d3-octree-1.1.0.tgz", - "integrity": "sha512-F8gPlqpP+HwRPMO/8uOu5wjH110+6q4cgJvgJT6vlpy3BEaDIKlTZrgHKZSp/i1InRpVfh4puY/kvL6MxK930A==", - "license": "MIT" - }, "node_modules/d3-path": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", @@ -4982,20 +4920,6 @@ "dev": true, "license": "ISC" }, - "node_modules/float-tooltip": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/float-tooltip/-/float-tooltip-1.7.5.tgz", - "integrity": "sha512-/kXzuDnnBqyyWyhDMH7+PfP8J/oXiAavGzcRxASOMRHFuReDtofizLLJsf7nnDLAfEaMW4pVWaXrAjtnglpEkg==", - "license": "MIT", - "dependencies": { - "d3-selection": "2 - 3", - "kapsule": "^1.16", - "preact": "10" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/for-each": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", @@ -5012,32 +4936,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/force-graph": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/force-graph/-/force-graph-1.51.0.tgz", - "integrity": "sha512-aTnihCmiMA0ItLJLCbrQYS9mzriopW24goFPgUnKAAmAlPogTSmFWqoBPMXzIfPb7bs04Hur5zEI4WYgLW3Sig==", - "license": "MIT", - "dependencies": { - "@tweenjs/tween.js": "18 - 25", - "accessor-fn": "1", - "bezier-js": "3 - 6", - "canvas-color-tracker": "^1.3", - "d3-array": "1 - 3", - "d3-drag": "2 - 3", - "d3-force-3d": "2 - 3", - "d3-scale": "1 - 4", - "d3-scale-chromatic": "1 - 3", - "d3-selection": "2 - 3", - "d3-zoom": "2 - 3", - "float-tooltip": "^1.7", - "index-array-by": "1", - "kapsule": "^1.16", - "lodash-es": "4" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/format": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", @@ -5454,15 +5352,6 @@ "node": ">=0.8.19" } }, - "node_modules/index-array-by": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/index-array-by/-/index-array-by-1.4.2.tgz", - "integrity": "sha512-SP23P27OUKzXWEC/TOyWlwLviofQkCSCKONnc62eItjp69yCZZPqDQtr3Pw5gJDnPeUMqExmKydNZaJO0FU9pw==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", @@ -6057,18 +5946,6 @@ "node": ">=4.0" } }, - "node_modules/kapsule": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/kapsule/-/kapsule-1.16.3.tgz", - "integrity": "sha512-4+5mNNf4vZDSwPhKprKwz3330iisPrb08JyMgbsdFrimBCKNHecua/WBwvVg3n7vwx0C1ARjfhwIpbrbd9n5wg==", - "license": "MIT", - "dependencies": { - "lodash-es": "4" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -6862,16 +6739,6 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "license": "MIT" }, - "node_modules/preact": { - "version": "10.28.1", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.28.1.tgz", - "integrity": "sha512-u1/ixq/lVQI0CakKNvLDEcW5zfCjUQfZdK9qqWuIJtsezuyG6pk9TWj75GMuI/EzRSZB/VAE43sNWWZfiy8psw==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/preact" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -7943,12 +7810,6 @@ "node": ">=0.8" } }, - "node_modules/tinycolor2": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", - "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", - "license": "MIT" - }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", diff --git a/package.json b/package.json index a9aeeea8..626b5523 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@falkordb/canvas": "^0.0.38", + "@falkordb/canvas": "v0.0.40", "@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dropdown-menu": "^2.1.6", From a7d8ef2c2e84c9cf8adc1dc65ee987676943eb7e Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Wed, 25 Feb 2026 16:09:16 +0200 Subject: [PATCH 168/189] Update @falkordb/canvas dependency version to use caret notation for flexibility --- package-lock.json | 183 ++++++++++++++++++++++++++++++++++++++++------ package.json | 4 +- 2 files changed, 163 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index 52f8d36d..e206ca0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "code-graph", "version": "0.2.0", "dependencies": { - "@falkordb/canvas": "v0.0.40", + "@falkordb/canvas": "^0.0.40", "@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dropdown-menu": "^2.1.6", @@ -52,25 +52,6 @@ "typescript": "^5.7.3" } }, - "../falkordb-canvas": { - "name": "@falkordb/canvas", - "version": "0.0.40", - "license": "MIT", - "dependencies": { - "d3": "^7.9.0", - "force-graph": "^1.44.4", - "react": "^19.2.3" - }, - "devDependencies": { - "@types/d3": "^7.4.3", - "@types/react": "^19.2.7", - "@typescript-eslint/eslint-plugin": "^8.18.2", - "@typescript-eslint/parser": "^8.18.2", - "eslint": "^9.17.0", - "tsup": "^8.5.1", - "typescript": "^5.9.3" - } - }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", @@ -270,8 +251,24 @@ } }, "node_modules/@falkordb/canvas": { - "resolved": "../falkordb-canvas", - "link": true + "version": "0.0.40", + "resolved": "https://registry.npmjs.org/@falkordb/canvas/-/canvas-0.0.40.tgz", + "integrity": "sha512-sEIl10QHUXT5oGXkdLxY8saxStVQSxKfYd2THxJ4bjR77eq9L+OI8KYY5WRunX3UiZhfPiOy9PLaHHq0IuM8jg==", + "license": "MIT", + "dependencies": { + "d3": "^7.9.0", + "force-graph": "^1.44.4", + "react": "^19.2.3" + } + }, + "node_modules/@falkordb/canvas/node_modules/react": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, "node_modules/@floating-ui/core": { "version": "1.7.3", @@ -2135,6 +2132,12 @@ "tslib": "^2.8.0" } }, + "node_modules/@tweenjs/tween.js": { + "version": "25.0.0", + "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-25.0.0.tgz", + "integrity": "sha512-XKLA6syeBUaPzx4j3qwMqzzq+V4uo72BnlbOjmuljLrRqdsd3qnzvZZoxvMHZ23ndsRS4aufU6JOZYpCbU6T1A==", + "license": "MIT" + }, "node_modules/@tybys/wasm-util": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", @@ -2765,6 +2768,15 @@ "win32" ] }, + "node_modules/accessor-fn": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/accessor-fn/-/accessor-fn-1.5.3.tgz", + "integrity": "sha512-rkAofCwe/FvYFUlMB0v0gWmhqtfAtV1IUkdPbfhTUyYniu5LrC0A0UJkTH0Jv3S8SvwkmfuAlY+mQIJATdocMA==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", @@ -3149,6 +3161,16 @@ "baseline-browser-mapping": "dist/cli.js" } }, + "node_modules/bezier-js": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/bezier-js/-/bezier-js-6.1.4.tgz", + "integrity": "sha512-PA0FW9ZpcHbojUCMu28z9Vg/fNkwTj5YhusSAjHHDfHDGLxJ6YUKrAN2vk1fP2MMOxVw4Oko16FMlRGVBGqLKg==", + "license": "MIT", + "funding": { + "type": "individual", + "url": "https://github.com/Pomax/bezierjs/blob/master/FUNDING.md" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -3306,6 +3328,18 @@ ], "license": "CC-BY-4.0" }, + "node_modules/canvas-color-tracker": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/canvas-color-tracker/-/canvas-color-tracker-1.3.2.tgz", + "integrity": "sha512-ryQkDX26yJ3CXzb3hxUVNlg1NKE4REc5crLBq661Nxzr8TNd236SaEf2ffYLXyI5tSABSeguHLqcVq4vf9L3Zg==", + "license": "MIT", + "dependencies": { + "tinycolor2": "^1.6.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/canvas2svg": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/canvas2svg/-/canvas2svg-1.0.16.tgz", @@ -3593,6 +3627,12 @@ "node": ">=12" } }, + "node_modules/d3-binarytree": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d3-binarytree/-/d3-binarytree-1.0.2.tgz", + "integrity": "sha512-cElUNH+sHu95L04m92pG73t2MEJXKu+GeKUN1TJkFsu93E5W8E9Sc3kHEGJKgenGvj19m6upSn2EunvMgMD2Yw==", + "license": "MIT" + }, "node_modules/d3-brush": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", @@ -3736,6 +3776,22 @@ "node": ">=12" } }, + "node_modules/d3-force-3d": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/d3-force-3d/-/d3-force-3d-3.0.6.tgz", + "integrity": "sha512-4tsKHUPLOVkyfEffZo1v6sFHvGFwAIIjt/W8IThbp08DYAsXZck+2pSHEG5W1+gQgEvFLdZkYvmJAbRM2EzMnA==", + "license": "MIT", + "dependencies": { + "d3-binarytree": "1", + "d3-dispatch": "1 - 3", + "d3-octree": "1", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/d3-format": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", @@ -3778,6 +3834,12 @@ "node": ">=12" } }, + "node_modules/d3-octree": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-octree/-/d3-octree-1.1.0.tgz", + "integrity": "sha512-F8gPlqpP+HwRPMO/8uOu5wjH110+6q4cgJvgJT6vlpy3BEaDIKlTZrgHKZSp/i1InRpVfh4puY/kvL6MxK930A==", + "license": "MIT" + }, "node_modules/d3-path": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", @@ -4920,6 +4982,20 @@ "dev": true, "license": "ISC" }, + "node_modules/float-tooltip": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/float-tooltip/-/float-tooltip-1.7.5.tgz", + "integrity": "sha512-/kXzuDnnBqyyWyhDMH7+PfP8J/oXiAavGzcRxASOMRHFuReDtofizLLJsf7nnDLAfEaMW4pVWaXrAjtnglpEkg==", + "license": "MIT", + "dependencies": { + "d3-selection": "2 - 3", + "kapsule": "^1.16", + "preact": "10" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/for-each": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", @@ -4936,6 +5012,32 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/force-graph": { + "version": "1.51.1", + "resolved": "https://registry.npmjs.org/force-graph/-/force-graph-1.51.1.tgz", + "integrity": "sha512-uEEX8iRzgq1IKRISOw6RrB2RLMhcI25xznQYrCTVvxZHZZ+A2jH6qIolYuwavVxAMi64pFp2yZm4KFVdD993cg==", + "license": "MIT", + "dependencies": { + "@tweenjs/tween.js": "18 - 25", + "accessor-fn": "1", + "bezier-js": "3 - 6", + "canvas-color-tracker": "^1.3", + "d3-array": "1 - 3", + "d3-drag": "2 - 3", + "d3-force-3d": "2 - 3", + "d3-scale": "1 - 4", + "d3-scale-chromatic": "1 - 3", + "d3-selection": "2 - 3", + "d3-zoom": "2 - 3", + "float-tooltip": "^1.7", + "index-array-by": "1", + "kapsule": "^1.16", + "lodash-es": "4" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/format": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", @@ -5352,6 +5454,15 @@ "node": ">=0.8.19" } }, + "node_modules/index-array-by": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/index-array-by/-/index-array-by-1.4.2.tgz", + "integrity": "sha512-SP23P27OUKzXWEC/TOyWlwLviofQkCSCKONnc62eItjp69yCZZPqDQtr3Pw5gJDnPeUMqExmKydNZaJO0FU9pw==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", @@ -5946,6 +6057,18 @@ "node": ">=4.0" } }, + "node_modules/kapsule": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/kapsule/-/kapsule-1.16.3.tgz", + "integrity": "sha512-4+5mNNf4vZDSwPhKprKwz3330iisPrb08JyMgbsdFrimBCKNHecua/WBwvVg3n7vwx0C1ARjfhwIpbrbd9n5wg==", + "license": "MIT", + "dependencies": { + "lodash-es": "4" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -6739,6 +6862,16 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "license": "MIT" }, + "node_modules/preact": { + "version": "10.28.4", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.28.4.tgz", + "integrity": "sha512-uKFfOHWuSNpRFVTnljsCluEFq57OKT+0QdOiQo8XWnQ/pSvg7OpX5eNOejELXJMWy+BwM2nobz0FkvzmnpCNsQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -7810,6 +7943,12 @@ "node": ">=0.8" } }, + "node_modules/tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", diff --git a/package.json b/package.json index 626b5523..646de52f 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@falkordb/canvas": "v0.0.40", + "@falkordb/canvas": "^0.0.40", "@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dropdown-menu": "^2.1.6", @@ -53,4 +53,4 @@ "tailwindcss": "^3.4.17", "typescript": "^5.7.3" } -} \ No newline at end of file +} From 6cc12a26e84b540502c914a3a7fa8f76d49e8b46 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Thu, 26 Feb 2026 11:57:32 +0200 Subject: [PATCH 169/189] fix pom --- e2e/logic/POM/codeGraph.ts | 48 +++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 99b02355..e339c61c 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -520,6 +520,16 @@ export default class CodeGraph extends BasePage { await this.page.mouse.up(); } + async dragFromCanvasCenter(): Promise { + const box = (await this.canvasElement.boundingBox())!; + const centerX = box.x + box.width / 2; + const centerY = box.y + box.height / 2; + await this.page.mouse.move(centerX, centerY); + await this.page.mouse.down(); + await this.page.mouse.move(centerX + 100, centerY + 50); + await this.page.mouse.up(); + } + async isNodeDetailsPanel(): Promise { await this.page.waitForTimeout(500); return this.nodeDetailsPanel.isVisible(); @@ -586,20 +596,24 @@ export default class CodeGraph extends BasePage { return Promise.all(elements.map(element => element.innerHTML())); } - async getGraphNodes(): Promise { + private async waitForGraphData(): Promise { await this.waitForCanvasAnimationToEnd(); - // Wait for the graph data to be available on window object (set by handleEngineStop) + // Wait for the graph data to be available await this.page.waitForFunction(() => { - const data = (window as any).graphDesktop(); - // Check both possible structures: { nodes } or { elements: { nodes } } + const data = (window as any).graphDesktop?.(); return data && ((Array.isArray(data.nodes) && data.nodes.length > 0) || (data.elements && Array.isArray(data.elements.nodes) && data.elements.nodes.length > 0)); - }, - { timeout: 5000 }); + }, { timeout: 5000 }); - const graphData = await this.page.evaluate(() => { - return (window as any).graphDesktop(); - }); + // Safety guard: wait for engine to fully stop and data to settle + await this.page.waitForTimeout(3000); + await this.waitForCanvasAnimationToEnd(); + + return await this.page.evaluate(() => (window as any).graphDesktop()); + } + + async getGraphNodes(): Promise { + const graphData = await this.waitForGraphData(); let transformData: any = null; for (let attempt = 0; attempt < 3; attempt++) { @@ -686,21 +700,7 @@ export default class CodeGraph extends BasePage { async getGraphDetails(): Promise { await this.canvasElementBeforeGraphSelection.waitFor({ state: 'detached' }); - await this.waitForCanvasAnimationToEnd(); - - // Wait for the graph function to be available and return data - await this.page.waitForFunction(() => { - const data = (window as any).graph?.(); - // Check both possible structures: { nodes } or { elements: { nodes } } - return data && ((Array.isArray(data.nodes) && data.nodes.length > 0) || - (data.elements && Array.isArray(data.elements.nodes) && data.elements.nodes.length > 0)); - }, { timeout: 5000 }); - - const graphData = await this.page.evaluate(() => { - return (window as any).graph?.(); - }); - - return graphData; + return await this.waitForGraphData(); } async waitForCanvasAnimationToEnd(timeout = 4500): Promise { From 4e5be84df9df73dbe3313608a8ed1ed2f418e8e2 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Thu, 26 Feb 2026 11:57:53 +0200 Subject: [PATCH 170/189] fix canvas tests --- e2e/tests/canvas.spec.ts | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/e2e/tests/canvas.spec.ts b/e2e/tests/canvas.spec.ts index eac29290..a53a8fa0 100644 --- a/e2e/tests/canvas.spec.ts +++ b/e2e/tests/canvas.spec.ts @@ -64,7 +64,8 @@ test.describe("Canvas tests", () => { await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); await codeGraph.clickOnRemoveNodeViaElementMenu(); const updatedGraph = await codeGraph.getGraphNodes(); - expect(updatedGraph.length).toBeLessThan(initialCount); + const updatedNode = findNodeByName(updatedGraph, nodes[0].nodeName); + expect(updatedNode.visible).toBe(false); }); test(`Validate unhide node functionality after hiding a node in canvas for ${nodes[0].nodeName}`, async () => { @@ -88,7 +89,7 @@ test.describe("Canvas tests", () => { await codeGraph.selectCodeGraphCheckbox(checkboxIndex.toString()); const result = await codeGraph.getGraphNodes(); const findItem = result.find((item: { category: string; }) => item.category === category); - expect(findItem).toBeUndefined(); + expect(findItem.visible).toBeFalsy(); }); }) @@ -126,17 +127,28 @@ test.describe("Canvas tests", () => { }); }) - for (let index = 0; index < 3; index++) { + for (let index = 1; index < 3; index++) { const nodeIndex: number = index + 1; test(`Validate canvas node dragging for node: ${index}`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await browser.setPageToFullScreen(); await codeGraph.selectGraph(GRAPHRAG_SDK); const initialGraph = await codeGraph.getGraphNodes(); - await codeGraph.changeNodePosition(initialGraph[nodeIndex].screenX, initialGraph[nodeIndex].screenY); + const nodeName = initialGraph[nodeIndex].name || initialGraph[nodeIndex].data?.name; + await codeGraph.fillSearchBar(nodeName); + await codeGraph.selectSearchBarOptionBtn("1"); + await codeGraph.waitForCanvasAnimationToEnd(); + const updatedGraph = await codeGraph.getGraphNodes(); + const targetNode = findNodeByName(updatedGraph, nodeName); + const initialX = targetNode.x; + const initialY = targetNode.y; + await codeGraph.dragFromCanvasCenter(); const updateGraph = await codeGraph.getGraphDetails(); const nodes = updateGraph.elements?.nodes || updateGraph.nodes; - expect(nodes[nodeIndex].x).not.toBe(initialGraph[nodeIndex].x); - expect(nodes[nodeIndex].y).not.toBe(initialGraph[nodeIndex].y); + const draggedNode = findNodeByName(nodes, nodeName); + + expect(draggedNode.x).not.toBe(initialX); + expect(draggedNode.y).not.toBe(initialY); }); } @@ -174,10 +186,10 @@ test.describe("Canvas tests", () => { await codeGraph.clickOnShowPathBtn("Show the path"); await codeGraph.insertInputForShowPath("1", firstNode); await codeGraph.insertInputForShowPath("2", secondNode); - const result = await codeGraph.getGraphDetails(); - const firstNodeRes = findNodeByName(result?.nodes, firstNode); + const result = await codeGraph.getGraphNodes(); + const firstNodeRes = findNodeByName(result, firstNode); - const secondnodeRes = findNodeByName(result?.nodes, secondNode); + const secondnodeRes = findNodeByName(result, secondNode); expect(firstNodeRes).toBeDefined(); expect(secondnodeRes).toBeDefined(); From 562b9954573a3724a5614ea5d714ab64bbafb9cc Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Thu, 26 Feb 2026 13:31:37 +0200 Subject: [PATCH 171/189] fix canvas tests --- e2e/tests/canvas.spec.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/e2e/tests/canvas.spec.ts b/e2e/tests/canvas.spec.ts index a53a8fa0..b3428bbd 100644 --- a/e2e/tests/canvas.spec.ts +++ b/e2e/tests/canvas.spec.ts @@ -57,9 +57,12 @@ test.describe("Canvas tests", () => { test(`Validate node hide functionality via element menu in canvas for ${nodes[0].nodeName}`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await browser.setPageToFullScreen(); await codeGraph.selectGraph(GRAPHRAG_SDK); + await codeGraph.fillSearchBar(nodes[0].nodeName); + await codeGraph.selectSearchBarOptionBtn("1"); + await codeGraph.waitForCanvasAnimationToEnd(); const initialGraph = await codeGraph.getGraphNodes(); - const initialCount = initialGraph.length; const targetNode = findNodeByName(initialGraph, nodes[0].nodeName); await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); await codeGraph.clickOnRemoveNodeViaElementMenu(); From 2b080c7ad9f0676907ff0efc7334fc42b157c090 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Thu, 26 Feb 2026 13:36:13 +0200 Subject: [PATCH 172/189] Implement feature X to enhance user experience and optimize performance --- package-lock.json | 787 ++++++++++++++++++++-------------------------- 1 file changed, 349 insertions(+), 438 deletions(-) diff --git a/package-lock.json b/package-lock.json index e206ca0a..de766618 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,6 +52,25 @@ "typescript": "^5.7.3" } }, + "../falkordb-canvas": { + "name": "@falkordb/canvas", + "version": "0.0.40", + "license": "MIT", + "dependencies": { + "d3": "^7.9.0", + "force-graph": "^1.44.4", + "react": "^19.2.3" + }, + "devDependencies": { + "@types/d3": "^7.4.3", + "@types/react": "^19.2.7", + "@typescript-eslint/eslint-plugin": "^8.18.2", + "@typescript-eslint/parser": "^8.18.2", + "eslint": "^9.17.0", + "tsup": "^8.5.1", + "typescript": "^5.9.3" + } + }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", @@ -65,9 +84,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", - "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -86,9 +105,9 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", - "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", "license": "MIT", "optional": true, "dependencies": { @@ -107,9 +126,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", - "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -190,20 +209,20 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", - "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.4.tgz", + "integrity": "sha512-4h4MVF8pmBsncB60r0wSJiIeUKTSD4m7FmTFThG8RHlsg9ajqckLm9OraguFGZE4vVdpiI1Q4+hFnisopmG6gQ==", "dev": true, "license": "MIT", "dependencies": { - "ajv": "^6.12.4", + "ajv": "^6.14.0", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", - "minimatch": "^3.1.2", + "minimatch": "^3.1.3", "strip-json-comments": "^3.1.1" }, "engines": { @@ -214,9 +233,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", - "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", + "version": "9.39.3", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.3.tgz", + "integrity": "sha512-1B1VkCq6FuUNlQvlBYb+1jDu/gV297TIs/OeiaSR9l1H27SVW55ONE1e1Vp16NqP683+xEGzxYtv4XCiDPaQiw==", "dev": true, "license": "MIT", "engines": { @@ -251,51 +270,35 @@ } }, "node_modules/@falkordb/canvas": { - "version": "0.0.40", - "resolved": "https://registry.npmjs.org/@falkordb/canvas/-/canvas-0.0.40.tgz", - "integrity": "sha512-sEIl10QHUXT5oGXkdLxY8saxStVQSxKfYd2THxJ4bjR77eq9L+OI8KYY5WRunX3UiZhfPiOy9PLaHHq0IuM8jg==", - "license": "MIT", - "dependencies": { - "d3": "^7.9.0", - "force-graph": "^1.44.4", - "react": "^19.2.3" - } - }, - "node_modules/@falkordb/canvas/node_modules/react": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", - "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } + "resolved": "../falkordb-canvas", + "link": true }, "node_modules/@floating-ui/core": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", - "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.4.tgz", + "integrity": "sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==", "license": "MIT", "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "node_modules/@floating-ui/dom": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", - "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.5.tgz", + "integrity": "sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==", "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.7.3", + "@floating-ui/core": "^1.7.4", "@floating-ui/utils": "^0.2.10" } }, "node_modules/@floating-ui/react-dom": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz", - "integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.7.tgz", + "integrity": "sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg==", "license": "MIT", "dependencies": { - "@floating-ui/dom": "^1.7.4" + "@floating-ui/dom": "^1.7.5" }, "peerDependencies": { "react": ">=16.8.0", @@ -875,15 +878,15 @@ } }, "node_modules/@next/env": { - "version": "15.5.9", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.9.tgz", - "integrity": "sha512-4GlTZ+EJM7WaW2HEZcyU317tIQDjkQIyENDLxYJfSWlfqguN+dHkZgyQTV/7ykvobU7yEH5gKvreNrH4B6QgIg==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.12.tgz", + "integrity": "sha512-pUvdJN1on574wQHjaBfNGDt9Mz5utDSZFsIIQkMzPgNS8ZvT4H2mwOrOIClwsQOb6EGx5M76/CZr6G8i6pSpLg==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { - "version": "15.5.9", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.5.9.tgz", - "integrity": "sha512-kUzXx0iFiXw27cQAViE1yKWnz/nF8JzRmwgMRTMh8qMY90crNsdXJRh2e+R0vBpFR3kk1yvAR7wev7+fCCb79Q==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.5.12.tgz", + "integrity": "sha512-+ZRSDFTv4aC96aMb5E41rMjysx8ApkryevnvEYZvPZO52KvkqP5rNExLUXJFr9P4s0f3oqNQR6vopCZsPWKDcQ==", "dev": true, "license": "MIT", "dependencies": { @@ -891,9 +894,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.7.tgz", - "integrity": "sha512-IZwtxCEpI91HVU/rAUOOobWSZv4P2DeTtNaCdHqLcTJU4wdNXgAySvKa/qJCgR5m6KI8UsKDXtO2B31jcaw1Yw==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.12.tgz", + "integrity": "sha512-RnRjBtH8S8eXCpUNkQ+543DUc7ys8y15VxmFU9HRqlo9BG3CcBUiwNtF8SNoi2xvGCVJq1vl2yYq+3oISBS0Zg==", "cpu": [ "arm64" ], @@ -907,9 +910,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.7.tgz", - "integrity": "sha512-UP6CaDBcqaCBuiq/gfCEJw7sPEoX1aIjZHnBWN9v9qYHQdMKvCKcAVs4OX1vIjeE+tC5EIuwDTVIoXpUes29lg==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.12.tgz", + "integrity": "sha512-nqa9/7iQlboF1EFtNhWxQA0rQstmYRSBGxSM6g3GxvxHxcoeqVXfGNr9stJOme674m2V7r4E3+jEhhGvSQhJRA==", "cpu": [ "x64" ], @@ -923,9 +926,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.7.tgz", - "integrity": "sha512-NCslw3GrNIw7OgmRBxHtdWFQYhexoUCq+0oS2ccjyYLtcn1SzGzeM54jpTFonIMUjNbHmpKpziXnpxhSWLcmBA==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.12.tgz", + "integrity": "sha512-dCzAjqhDHwmoB2M4eYfVKqXs99QdQxNQVpftvP1eGVppamXh/OkDAwV737Zr0KPXEqRUMN4uCjh6mjO+XtF3Mw==", "cpu": [ "arm64" ], @@ -939,9 +942,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.7.tgz", - "integrity": "sha512-nfymt+SE5cvtTrG9u1wdoxBr9bVB7mtKTcj0ltRn6gkP/2Nu1zM5ei8rwP9qKQP0Y//umK+TtkKgNtfboBxRrw==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.12.tgz", + "integrity": "sha512-+fpGWvQiITgf7PUtbWY1H7qUSnBZsPPLyyq03QuAKpVoTy/QUx1JptEDTQMVvQhvizCEuNLEeghrQUyXQOekuw==", "cpu": [ "arm64" ], @@ -955,9 +958,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.7.tgz", - "integrity": "sha512-hvXcZvCaaEbCZcVzcY7E1uXN9xWZfFvkNHwbe/n4OkRhFWrs1J1QV+4U1BN06tXLdaS4DazEGXwgqnu/VMcmqw==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.12.tgz", + "integrity": "sha512-jSLvgdRRL/hrFAPqEjJf1fFguC719kmcptjNVDJl26BnJIpjL3KH5h6mzR4mAweociLQaqvt4UyzfbFjgAdDcw==", "cpu": [ "x64" ], @@ -971,9 +974,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.7.tgz", - "integrity": "sha512-4IUO539b8FmF0odY6/SqANJdgwn1xs1GkPO5doZugwZ3ETF6JUdckk7RGmsfSf7ws8Qb2YB5It33mvNL/0acqA==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.12.tgz", + "integrity": "sha512-/uaF0WfmYqQgLfPmN6BvULwxY0dufI2mlN2JbOKqqceZh1G4hjREyi7pg03zjfyS6eqNemHAZPSoP84x17vo6w==", "cpu": [ "x64" ], @@ -987,9 +990,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.7.tgz", - "integrity": "sha512-CpJVTkYI3ZajQkC5vajM7/ApKJUOlm6uP4BknM3XKvJ7VXAvCqSjSLmM0LKdYzn6nBJVSjdclx8nYJSa3xlTgQ==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.12.tgz", + "integrity": "sha512-xhsL1OvQSfGmlL5RbOmU+FV120urrgFpYLq+6U8C6KIym32gZT6XF/SDE92jKzzlPWskkbjOKCpqk5m4i8PEfg==", "cpu": [ "arm64" ], @@ -1003,9 +1006,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.7.tgz", - "integrity": "sha512-gMzgBX164I6DN+9/PGA+9dQiwmTkE4TloBNx8Kv9UiGARsr9Nba7IpcBRA1iTV9vwlYnrE3Uy6I7Aj6qLjQuqw==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.12.tgz", + "integrity": "sha512-Z1Dh6lhFkxvBDH1FoW6OU/L6prYwPSlwjLiZkExIAh8fbP6iI/M7iGTQAJPYJ9YFlWobCZ1PHbchFhFYb2ADkw==", "cpu": [ "x64" ], @@ -1064,63 +1067,17 @@ } }, "node_modules/@playwright/test": { - "version": "1.57.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.57.0.tgz", - "integrity": "sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "playwright": "1.57.0" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@playwright/test/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/@playwright/test/node_modules/playwright": { - "version": "1.57.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.57.0.tgz", - "integrity": "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==", + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.2.tgz", + "integrity": "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.57.0" + "playwright": "1.58.2" }, "bin": { "playwright": "cli.js" }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "fsevents": "2.3.2" - } - }, - "node_modules/@playwright/test/node_modules/playwright-core": { - "version": "1.57.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.57.0.tgz", - "integrity": "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==", - "devOptional": true, - "license": "Apache-2.0", - "bin": { - "playwright-core": "cli.js" - }, "engines": { "node": ">=18" } @@ -2117,9 +2074,9 @@ "license": "MIT" }, "node_modules/@rushstack/eslint-patch": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.15.0.tgz", - "integrity": "sha512-ojSshQPKwVvSMR8yT2L/QtUkV5SXi/IfDiJ4/8d6UbTPjiHVmxZzUAzGD8Tzks1b9+qQkZa0isUOvYObedITaw==", + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.16.1.tgz", + "integrity": "sha512-TvZbIpeKqGQQ7X0zSCvPH9riMSFQFSggnfBjFZ1mEoILW+UuXCKwOoPcgjMwiUtRqFZ8jWhPJc4um14vC6I4ag==", "dev": true, "license": "MIT" }, @@ -2132,12 +2089,6 @@ "tslib": "^2.8.0" } }, - "node_modules/@tweenjs/tween.js": { - "version": "25.0.0", - "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-25.0.0.tgz", - "integrity": "sha512-XKLA6syeBUaPzx4j3qwMqzzq+V4uo72BnlbOjmuljLrRqdsd3qnzvZZoxvMHZ23ndsRS4aufU6JOZYpCbU6T1A==", - "license": "MIT" - }, "node_modules/@tybys/wasm-util": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", @@ -2180,15 +2131,15 @@ "license": "MIT" }, "node_modules/@types/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-FOvQ0YPD5NOfPgMzJihoT+Za5pdkDJWcbpuj1DjaKZIr/gxodQjY/uWEFlTNqW2ugXHUiL8lRQgw63dzKHZdeQ==", + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz", + "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==", "license": "MIT" }, "node_modules/@types/node": { - "version": "20.19.27", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.27.tgz", - "integrity": "sha512-N2clP5pJhB2YnZJ3PIHFk5RkygRX5WO/5f0WC08tp0wd+sv0rsJk3MqWn3CbNmT2J505a5336jaQj4ph1AdMug==", + "version": "20.19.34", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.34.tgz", + "integrity": "sha512-by3/Z0Qp+L9cAySEsSNNwZ6WWw8ywgGLPQGgbQDhNRSitqYgkgp4pErd23ZSCavbtUA2CN4jQtoB3T8nk4j3Rg==", "dev": true, "license": "MIT", "dependencies": { @@ -2202,9 +2153,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "18.3.27", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz", - "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==", + "version": "18.3.28", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", + "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -2244,20 +2195,20 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.51.0.tgz", - "integrity": "sha512-XtssGWJvypyM2ytBnSnKtHYOGT+4ZwTnBVl36TA4nRO2f4PRNGz5/1OszHzcZCvcBMh+qb7I06uoCmLTRdR9og==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.1.tgz", + "integrity": "sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.51.0", - "@typescript-eslint/type-utils": "8.51.0", - "@typescript-eslint/utils": "8.51.0", - "@typescript-eslint/visitor-keys": "8.51.0", - "ignore": "^7.0.0", + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.56.1", + "@typescript-eslint/type-utils": "8.56.1", + "@typescript-eslint/utils": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1", + "ignore": "^7.0.5", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.2.0" + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2267,8 +2218,8 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.51.0", - "eslint": "^8.57.0 || ^9.0.0", + "@typescript-eslint/parser": "^8.56.1", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, @@ -2283,17 +2234,17 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.51.0.tgz", - "integrity": "sha512-3xP4XzzDNQOIqBMWogftkwxhg5oMKApqY0BAflmLZiFYHqyhSOxv/cd/zPQLTcCXr4AkaKb25joocY0BD1WC6A==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.1.tgz", + "integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.51.0", - "@typescript-eslint/types": "8.51.0", - "@typescript-eslint/typescript-estree": "8.51.0", - "@typescript-eslint/visitor-keys": "8.51.0", - "debug": "^4.3.4" + "@typescript-eslint/scope-manager": "8.56.1", + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/typescript-estree": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2303,20 +2254,20 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.51.0.tgz", - "integrity": "sha512-Luv/GafO07Z7HpiI7qeEW5NW8HUtZI/fo/kE0YbtQEFpJRUuR0ajcWfCE5bnMvL7QQFrmT/odMe8QZww8X2nfQ==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.1.tgz", + "integrity": "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.51.0", - "@typescript-eslint/types": "^8.51.0", - "debug": "^4.3.4" + "@typescript-eslint/tsconfig-utils": "^8.56.1", + "@typescript-eslint/types": "^8.56.1", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2330,14 +2281,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.51.0.tgz", - "integrity": "sha512-JhhJDVwsSx4hiOEQPeajGhCWgBMBwVkxC/Pet53EpBVs7zHHtayKefw1jtPaNRXpI9RA2uocdmpdfE7T+NrizA==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.1.tgz", + "integrity": "sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.51.0", - "@typescript-eslint/visitor-keys": "8.51.0" + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2348,9 +2299,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.51.0.tgz", - "integrity": "sha512-Qi5bSy/vuHeWyir2C8u/uqGMIlIDu8fuiYWv48ZGlZ/k+PRPHtaAu7erpc7p5bzw2WNNSniuxoMSO4Ar6V9OXw==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.1.tgz", + "integrity": "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==", "dev": true, "license": "MIT", "engines": { @@ -2365,17 +2316,17 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.51.0.tgz", - "integrity": "sha512-0XVtYzxnobc9K0VU7wRWg1yiUrw4oQzexCG2V2IDxxCxhqBMSMbjB+6o91A+Uc0GWtgjCa3Y8bi7hwI0Tu4n5Q==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.1.tgz", + "integrity": "sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.51.0", - "@typescript-eslint/typescript-estree": "8.51.0", - "@typescript-eslint/utils": "8.51.0", - "debug": "^4.3.4", - "ts-api-utils": "^2.2.0" + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/typescript-estree": "8.56.1", + "@typescript-eslint/utils": "8.56.1", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2385,14 +2336,14 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.51.0.tgz", - "integrity": "sha512-TizAvWYFM6sSscmEakjY3sPqGwxZRSywSsPEiuZF6d5GmGD9Gvlsv0f6N8FvAAA0CD06l3rIcWNbsN1e5F/9Ag==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.1.tgz", + "integrity": "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==", "dev": true, "license": "MIT", "engines": { @@ -2404,21 +2355,21 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.51.0.tgz", - "integrity": "sha512-1qNjGqFRmlq0VW5iVlcyHBbCjPB7y6SxpBkrbhNWMy/65ZoncXCEPJxkRZL8McrseNH6lFhaxCIaX+vBuFnRng==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.1.tgz", + "integrity": "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.51.0", - "@typescript-eslint/tsconfig-utils": "8.51.0", - "@typescript-eslint/types": "8.51.0", - "@typescript-eslint/visitor-keys": "8.51.0", - "debug": "^4.3.4", - "minimatch": "^9.0.4", - "semver": "^7.6.0", + "@typescript-eslint/project-service": "8.56.1", + "@typescript-eslint/tsconfig-utils": "8.56.1", + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.2.0" + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2431,43 +2382,56 @@ "typescript": ">=4.8.4 <6.0.0" } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.3.tgz", + "integrity": "sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^5.0.2" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/@typescript-eslint/utils": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.51.0.tgz", - "integrity": "sha512-11rZYxSe0zabiKaCP2QAwRf/dnmgFgvTmeDTtZvUvXG3UuAdg/GU02NExmmIXzz3vLGgMdtrIosI84jITQOxUA==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.1.tgz", + "integrity": "sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.51.0", - "@typescript-eslint/types": "8.51.0", - "@typescript-eslint/typescript-estree": "8.51.0" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.56.1", + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/typescript-estree": "8.56.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2477,19 +2441,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.51.0.tgz", - "integrity": "sha512-mM/JRQOzhVN1ykejrvwnBRV3+7yTKK8tVANVN3o1O0t0v7o+jqdVu9crPy5Y9dov15TJk/FTIgoUGHrTOVL3Zg==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.1.tgz", + "integrity": "sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.51.0", - "eslint-visitor-keys": "^4.2.1" + "@typescript-eslint/types": "8.56.1", + "eslint-visitor-keys": "^5.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2499,6 +2463,19 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@unrs/resolver-binding-android-arm-eabi": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", @@ -2768,19 +2745,10 @@ "win32" ] }, - "node_modules/accessor-fn": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/accessor-fn/-/accessor-fn-1.5.3.tgz", - "integrity": "sha512-rkAofCwe/FvYFUlMB0v0gWmhqtfAtV1IUkdPbfhTUyYniu5LrC0A0UJkTH0Jv3S8SvwkmfuAlY+mQIJATdocMA==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", "bin": { @@ -2801,9 +2769,9 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", "dependencies": { @@ -3065,9 +3033,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.23", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.23.tgz", - "integrity": "sha512-YYTXSFulfwytnjAPlw8QHncHJmlvFKtczb8InXaAx9Q0LbfDnfEYDE55omerIJKihhmU61Ft+cAOSzQVaBUmeA==", + "version": "10.4.27", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.27.tgz", + "integrity": "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==", "funding": [ { "type": "opencollective", @@ -3085,7 +3053,7 @@ "license": "MIT", "dependencies": { "browserslist": "^4.28.1", - "caniuse-lite": "^1.0.30001760", + "caniuse-lite": "^1.0.30001774", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" @@ -3117,9 +3085,9 @@ } }, "node_modules/axe-core": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.0.tgz", - "integrity": "sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.1.tgz", + "integrity": "sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A==", "dev": true, "license": "MPL-2.0", "engines": { @@ -3153,22 +3121,15 @@ } }, "node_modules/baseline-browser-mapping": { - "version": "2.9.11", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz", - "integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", + "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", "license": "Apache-2.0", "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, - "node_modules/bezier-js": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/bezier-js/-/bezier-js-6.1.4.tgz", - "integrity": "sha512-PA0FW9ZpcHbojUCMu28z9Vg/fNkwTj5YhusSAjHHDfHDGLxJ6YUKrAN2vk1fP2MMOxVw4Oko16FMlRGVBGqLKg==", - "license": "MIT", - "funding": { - "type": "individual", - "url": "https://github.com/Pomax/bezierjs/blob/master/FUNDING.md" + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/binary-extensions": { @@ -3309,9 +3270,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001762", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001762.tgz", - "integrity": "sha512-PxZwGNvH7Ak8WX5iXzoK1KPZttBXNPuaOvI2ZYU7NrlM+d9Ov+TUvlLOBNGzVXAntMSMMlJPd+jY6ovrVjSmUw==", + "version": "1.0.30001774", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001774.tgz", + "integrity": "sha512-DDdwPGz99nmIEv216hKSgLD+D4ikHQHjBC/seF98N9CPqRX4M5mSxT9eTV6oyisnJcuzxtZy4n17yKKQYmYQOA==", "funding": [ { "type": "opencollective", @@ -3328,18 +3289,6 @@ ], "license": "CC-BY-4.0" }, - "node_modules/canvas-color-tracker": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/canvas-color-tracker/-/canvas-color-tracker-1.3.2.tgz", - "integrity": "sha512-ryQkDX26yJ3CXzb3hxUVNlg1NKE4REc5crLBq661Nxzr8TNd236SaEf2ffYLXyI5tSABSeguHLqcVq4vf9L3Zg==", - "license": "MIT", - "dependencies": { - "tinycolor2": "^1.6.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/canvas2svg": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/canvas2svg/-/canvas2svg-1.0.16.tgz", @@ -3627,12 +3576,6 @@ "node": ">=12" } }, - "node_modules/d3-binarytree": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d3-binarytree/-/d3-binarytree-1.0.2.tgz", - "integrity": "sha512-cElUNH+sHu95L04m92pG73t2MEJXKu+GeKUN1TJkFsu93E5W8E9Sc3kHEGJKgenGvj19m6upSn2EunvMgMD2Yw==", - "license": "MIT" - }, "node_modules/d3-brush": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", @@ -3776,26 +3719,10 @@ "node": ">=12" } }, - "node_modules/d3-force-3d": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/d3-force-3d/-/d3-force-3d-3.0.6.tgz", - "integrity": "sha512-4tsKHUPLOVkyfEffZo1v6sFHvGFwAIIjt/W8IThbp08DYAsXZck+2pSHEG5W1+gQgEvFLdZkYvmJAbRM2EzMnA==", - "license": "MIT", - "dependencies": { - "d3-binarytree": "1", - "d3-dispatch": "1 - 3", - "d3-octree": "1", - "d3-quadtree": "1 - 3", - "d3-timer": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/d3-format": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", - "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", "license": "ISC", "engines": { "node": ">=12" @@ -3834,12 +3761,6 @@ "node": ">=12" } }, - "node_modules/d3-octree": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-octree/-/d3-octree-1.1.0.tgz", - "integrity": "sha512-F8gPlqpP+HwRPMO/8uOu5wjH110+6q4cgJvgJT6vlpy3BEaDIKlTZrgHKZSp/i1InRpVfh4puY/kvL6MxK930A==", - "license": "MIT" - }, "node_modules/d3-path": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", @@ -4182,9 +4103,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.267", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", - "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", + "version": "1.5.302", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.302.tgz", + "integrity": "sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==", "license": "ISC" }, "node_modules/embla-carousel": { @@ -4422,9 +4343,9 @@ } }, "node_modules/eslint": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", - "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", + "version": "9.39.3", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.3.tgz", + "integrity": "sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==", "dev": true, "license": "MIT", "dependencies": { @@ -4434,7 +4355,7 @@ "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.39.2", + "@eslint/js": "9.39.3", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -4482,13 +4403,13 @@ } }, "node_modules/eslint-config-next": { - "version": "15.5.9", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.5.9.tgz", - "integrity": "sha512-852JYI3NkFNzW8CqsMhI0K2CDRxTObdZ2jQJj5CtpEaOkYHn13107tHpNuD/h0WRpU4FAbCdUaxQsrfBtNK9Kw==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.5.12.tgz", + "integrity": "sha512-ktW3XLfd+ztEltY5scJNjxjHwtKWk6vU2iwzZqSN09UsbBmMeE/cVlJ1yESg6Yx5LW7p/Z8WzUAgYXGLEmGIpg==", "dev": true, "license": "MIT", "dependencies": { - "@next/eslint-plugin-next": "15.5.9", + "@next/eslint-plugin-next": "15.5.12", "@rushstack/eslint-patch": "^1.10.3", "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", @@ -4725,19 +4646,25 @@ } }, "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "version": "2.0.0-next.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.6.tgz", + "integrity": "sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==", "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -4801,9 +4728,9 @@ } }, "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -4982,20 +4909,6 @@ "dev": true, "license": "ISC" }, - "node_modules/float-tooltip": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/float-tooltip/-/float-tooltip-1.7.5.tgz", - "integrity": "sha512-/kXzuDnnBqyyWyhDMH7+PfP8J/oXiAavGzcRxASOMRHFuReDtofizLLJsf7nnDLAfEaMW4pVWaXrAjtnglpEkg==", - "license": "MIT", - "dependencies": { - "d3-selection": "2 - 3", - "kapsule": "^1.16", - "preact": "10" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/for-each": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", @@ -5012,32 +4925,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/force-graph": { - "version": "1.51.1", - "resolved": "https://registry.npmjs.org/force-graph/-/force-graph-1.51.1.tgz", - "integrity": "sha512-uEEX8iRzgq1IKRISOw6RrB2RLMhcI25xznQYrCTVvxZHZZ+A2jH6qIolYuwavVxAMi64pFp2yZm4KFVdD993cg==", - "license": "MIT", - "dependencies": { - "@tweenjs/tween.js": "18 - 25", - "accessor-fn": "1", - "bezier-js": "3 - 6", - "canvas-color-tracker": "^1.3", - "d3-array": "1 - 3", - "d3-drag": "2 - 3", - "d3-force-3d": "2 - 3", - "d3-scale": "1 - 4", - "d3-scale-chromatic": "1 - 3", - "d3-selection": "2 - 3", - "d3-zoom": "2 - 3", - "float-tooltip": "^1.7", - "index-array-by": "1", - "kapsule": "^1.16", - "lodash-es": "4" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/format": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", @@ -5060,9 +4947,9 @@ } }, "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5190,9 +5077,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", - "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "version": "4.13.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.6.tgz", + "integrity": "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==", "dev": true, "license": "MIT", "dependencies": { @@ -5454,15 +5341,6 @@ "node": ">=0.8.19" } }, - "node_modules/index-array-by": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/index-array-by/-/index-array-by-1.4.2.tgz", - "integrity": "sha512-SP23P27OUKzXWEC/TOyWlwLviofQkCSCKONnc62eItjp69yCZZPqDQtr3Pw5gJDnPeUMqExmKydNZaJO0FU9pw==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", @@ -6057,18 +5935,6 @@ "node": ">=4.0" } }, - "node_modules/kapsule": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/kapsule/-/kapsule-1.16.3.tgz", - "integrity": "sha512-4+5mNNf4vZDSwPhKprKwz3330iisPrb08JyMgbsdFrimBCKNHecua/WBwvVg3n7vwx0C1ARjfhwIpbrbd9n5wg==", - "license": "MIT", - "dependencies": { - "lodash-es": "4" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -6148,9 +6014,9 @@ } }, "node_modules/lodash-es": { - "version": "4.17.22", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.22.tgz", - "integrity": "sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", + "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", "license": "MIT" }, "node_modules/lodash.merge": { @@ -6228,9 +6094,9 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -6310,12 +6176,12 @@ "license": "MIT" }, "node_modules/next": { - "version": "15.5.9", - "resolved": "https://registry.npmjs.org/next/-/next-15.5.9.tgz", - "integrity": "sha512-agNLK89seZEtC5zUHwtut0+tNrc0Xw4FT/Dg+B/VLEo9pAcS9rtTKpek3V6kVcVwsB2YlqMaHdfZL4eLEVYuCg==", + "version": "15.5.12", + "resolved": "https://registry.npmjs.org/next/-/next-15.5.12.tgz", + "integrity": "sha512-Fi/wQ4Etlrn60rz78bebG1i1SR20QxvV8tVp6iJspjLUSHcZoeUXCt+vmWoEcza85ElZzExK/jJ/F6SvtGktjA==", "license": "MIT", "dependencies": { - "@next/env": "15.5.9", + "@next/env": "15.5.12", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", @@ -6328,14 +6194,14 @@ "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "15.5.7", - "@next/swc-darwin-x64": "15.5.7", - "@next/swc-linux-arm64-gnu": "15.5.7", - "@next/swc-linux-arm64-musl": "15.5.7", - "@next/swc-linux-x64-gnu": "15.5.7", - "@next/swc-linux-x64-musl": "15.5.7", - "@next/swc-win32-arm64-msvc": "15.5.7", - "@next/swc-win32-x64-msvc": "15.5.7", + "@next/swc-darwin-arm64": "15.5.12", + "@next/swc-darwin-x64": "15.5.12", + "@next/swc-linux-arm64-gnu": "15.5.12", + "@next/swc-linux-arm64-musl": "15.5.12", + "@next/swc-linux-x64-gnu": "15.5.12", + "@next/swc-linux-x64-musl": "15.5.12", + "@next/swc-win32-arm64-msvc": "15.5.12", + "@next/swc-win32-x64-msvc": "15.5.12", "sharp": "^0.34.3" }, "peerDependencies": { @@ -6389,6 +6255,35 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/node-exports-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz", + "integrity": "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/node-exports-info/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/node-releases": { "version": "2.0.27", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", @@ -6696,6 +6591,38 @@ "node": ">= 6" } }, + "node_modules/playwright": { + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz", + "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.58.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz", + "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -6862,16 +6789,6 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "license": "MIT" }, - "node_modules/preact": { - "version": "10.28.4", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.28.4.tgz", - "integrity": "sha512-uKFfOHWuSNpRFVTnljsCluEFq57OKT+0QdOiQo8XWnQ/pSvg7OpX5eNOejELXJMWy+BwM2nobz0FkvzmnpCNsQ==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/preact" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -7360,9 +7277,9 @@ } }, "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "devOptional": true, "license": "ISC", "bin": { @@ -7830,9 +7747,9 @@ } }, "node_modules/tailwind-merge": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.0.tgz", - "integrity": "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.1.tgz", + "integrity": "sha512-Oo6tHdpZsGpkKG88HJ8RR1rg/RdnEkQEfMoEk2x1XRI3F1AxeU+ijRXpiVUF4UbLfcxxRGw6TbUINKYdWVsQTQ==", "license": "MIT", "funding": { "type": "github", @@ -7943,12 +7860,6 @@ "node": ">=0.8" } }, - "node_modules/tinycolor2": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", - "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", - "license": "MIT" - }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -8007,9 +7918,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.3.0.tgz", - "integrity": "sha512-6eg3Y9SF7SsAvGzRHQvvc1skDAhwI4YQ32ui1scxD1Ccr0G5qIIbUBT3pFTKX8kmWIQClHobtUdNuaBgwdfdWg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", "dev": true, "license": "MIT", "engines": { @@ -8405,9 +8316,9 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.19", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", - "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", "dev": true, "license": "MIT", "dependencies": { From 772431afe85d9e6b77f9fa752bfc27ece442ce32 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Thu, 26 Feb 2026 13:54:57 +0200 Subject: [PATCH 173/189] fix nodeDetailsPanel tests --- e2e/tests/nodeDetailsPanel.spec.ts | 52 ++++++++++++++++-------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/e2e/tests/nodeDetailsPanel.spec.ts b/e2e/tests/nodeDetailsPanel.spec.ts index 7762b6db..730fbc35 100644 --- a/e2e/tests/nodeDetailsPanel.spec.ts +++ b/e2e/tests/nodeDetailsPanel.spec.ts @@ -5,7 +5,7 @@ import urls from "../config/urls.json"; import { FLASK_GRAPH, GRAPHRAG_SDK } from "../config/constants"; import { findNodeByName } from "../logic/utils"; import { nodes } from "../config/testData"; -import { ApiCalls } from "../logic/api/apiCalls"; + test.describe("Node details panel tests", () => { let browser: BrowserWrapper; @@ -23,8 +23,11 @@ test.describe("Node details panel tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await browser.setPageToFullScreen(); await codeGraph.selectGraph(GRAPHRAG_SDK); + await codeGraph.fillSearchBar(node.nodeName); + await codeGraph.selectSearchBarOptionBtn("1"); + await codeGraph.waitForCanvasAnimationToEnd(); const graphData = await codeGraph.getGraphNodes(); - + const targetNode = findNodeByName(graphData, node.nodeName); expect(targetNode).toBeDefined(); await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); @@ -38,6 +41,9 @@ test.describe("Node details panel tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await browser.setPageToFullScreen(); await codeGraph.selectGraph(GRAPHRAG_SDK); + await codeGraph.fillSearchBar(node.nodeName); + await codeGraph.selectSearchBarOptionBtn("1"); + await codeGraph.waitForCanvasAnimationToEnd(); const graphData = await codeGraph.getGraphNodes(); const targetNode = findNodeByName(graphData, node.nodeName); await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); @@ -52,6 +58,9 @@ test.describe("Node details panel tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await browser.setPageToFullScreen(); await codeGraph.selectGraph(GRAPHRAG_SDK); + await codeGraph.fillSearchBar(node.nodeName); + await codeGraph.selectSearchBarOptionBtn("1"); + await codeGraph.waitForCanvasAnimationToEnd(); const graphData = await codeGraph.getGraphNodes(); const targetNode = findNodeByName(graphData, node.nodeName); await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); @@ -65,42 +74,35 @@ test.describe("Node details panel tests", () => { await browser.setPageToFullScreen(); await codeGraph.selectGraph(FLASK_GRAPH); const graphData = await codeGraph.getGraphNodes(); - - // Find a node that has src property (actual source code) const targetNode = graphData.find(node => node.src) || graphData[0]; + const nodeName = targetNode.name || targetNode.data?.name; + await codeGraph.fillSearchBar(nodeName); + await codeGraph.selectSearchBarOptionBtn("1"); + await codeGraph.waitForCanvasAnimationToEnd(); - await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); + await codeGraph.rightClickAtCanvasCenter(); await codeGraph.clickOnViewNode(); const copiedText = await codeGraph.clickOnCopyToClipboardNodePanelDetails(); - - // Verify the copied text matches the node's src property expect(copiedText).toBe(targetNode.src || ""); }); + const expectedNodeKeys = ["id", "doc", "name", "path", "src_end", "src_start"]; + nodes.slice(0, 2).forEach((node) => { - test(`Validate view node panel keys via api for ${node.nodeName}`, async () => { + test(`Validate node data contains expected properties for ${node.nodeName}`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await browser.setPageToFullScreen(); await codeGraph.selectGraph(GRAPHRAG_SDK); + await codeGraph.fillSearchBar(node.nodeName); + await codeGraph.selectSearchBarOptionBtn("1"); + await codeGraph.waitForCanvasAnimationToEnd(); const graphData = await codeGraph.getGraphNodes(); - const node1 = findNodeByName(graphData, node.nodeName); - const api = new ApiCalls(); - const response = await api.getProject(GRAPHRAG_SDK); - const data: any = response.result.entities.nodes; - const findNode = data.find((nod: any) => nod.properties.name === node.nodeName); - await codeGraph.nodeClick(node1.screenX, node1.screenY); - let elements = await codeGraph.getNodeDetailsPanelElements(); - elements.splice(2, 1); - const apiFields = [ - ...Object.keys(findNode), - ...Object.keys(findNode.properties || {}), - ]; + const targetNode = findNodeByName(graphData, node.nodeName); + expect(targetNode).toBeDefined(); - const isValid = elements.every((field) => { - const cleanedField = field.replace(":", "").trim(); - return apiFields.includes(cleanedField); - }); - expect(isValid).toBe(true); + for (const key of expectedNodeKeys) { + expect(targetNode).toHaveProperty(key); + } }); }); }); From b8d9403bdf0e7a3641266fa7b04d7fb27c29e29e Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Thu, 26 Feb 2026 14:14:49 +0200 Subject: [PATCH 174/189] fix build --- package-lock.json | 181 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 160 insertions(+), 21 deletions(-) diff --git a/package-lock.json b/package-lock.json index de766618..565aff53 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,25 +52,6 @@ "typescript": "^5.7.3" } }, - "../falkordb-canvas": { - "name": "@falkordb/canvas", - "version": "0.0.40", - "license": "MIT", - "dependencies": { - "d3": "^7.9.0", - "force-graph": "^1.44.4", - "react": "^19.2.3" - }, - "devDependencies": { - "@types/d3": "^7.4.3", - "@types/react": "^19.2.7", - "@typescript-eslint/eslint-plugin": "^8.18.2", - "@typescript-eslint/parser": "^8.18.2", - "eslint": "^9.17.0", - "tsup": "^8.5.1", - "typescript": "^5.9.3" - } - }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", @@ -270,8 +251,24 @@ } }, "node_modules/@falkordb/canvas": { - "resolved": "../falkordb-canvas", - "link": true + "version": "0.0.40", + "resolved": "https://registry.npmjs.org/@falkordb/canvas/-/canvas-0.0.40.tgz", + "integrity": "sha512-sEIl10QHUXT5oGXkdLxY8saxStVQSxKfYd2THxJ4bjR77eq9L+OI8KYY5WRunX3UiZhfPiOy9PLaHHq0IuM8jg==", + "license": "MIT", + "dependencies": { + "d3": "^7.9.0", + "force-graph": "^1.44.4", + "react": "^19.2.3" + } + }, + "node_modules/@falkordb/canvas/node_modules/react": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, "node_modules/@floating-ui/core": { "version": "1.7.4", @@ -2089,6 +2086,12 @@ "tslib": "^2.8.0" } }, + "node_modules/@tweenjs/tween.js": { + "version": "25.0.0", + "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-25.0.0.tgz", + "integrity": "sha512-XKLA6syeBUaPzx4j3qwMqzzq+V4uo72BnlbOjmuljLrRqdsd3qnzvZZoxvMHZ23ndsRS4aufU6JOZYpCbU6T1A==", + "license": "MIT" + }, "node_modules/@tybys/wasm-util": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", @@ -2745,6 +2748,15 @@ "win32" ] }, + "node_modules/accessor-fn": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/accessor-fn/-/accessor-fn-1.5.3.tgz", + "integrity": "sha512-rkAofCwe/FvYFUlMB0v0gWmhqtfAtV1IUkdPbfhTUyYniu5LrC0A0UJkTH0Jv3S8SvwkmfuAlY+mQIJATdocMA==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/acorn": { "version": "8.16.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", @@ -3132,6 +3144,16 @@ "node": ">=6.0.0" } }, + "node_modules/bezier-js": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/bezier-js/-/bezier-js-6.1.4.tgz", + "integrity": "sha512-PA0FW9ZpcHbojUCMu28z9Vg/fNkwTj5YhusSAjHHDfHDGLxJ6YUKrAN2vk1fP2MMOxVw4Oko16FMlRGVBGqLKg==", + "license": "MIT", + "funding": { + "type": "individual", + "url": "https://github.com/Pomax/bezierjs/blob/master/FUNDING.md" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -3289,6 +3311,18 @@ ], "license": "CC-BY-4.0" }, + "node_modules/canvas-color-tracker": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/canvas-color-tracker/-/canvas-color-tracker-1.3.2.tgz", + "integrity": "sha512-ryQkDX26yJ3CXzb3hxUVNlg1NKE4REc5crLBq661Nxzr8TNd236SaEf2ffYLXyI5tSABSeguHLqcVq4vf9L3Zg==", + "license": "MIT", + "dependencies": { + "tinycolor2": "^1.6.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/canvas2svg": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/canvas2svg/-/canvas2svg-1.0.16.tgz", @@ -3576,6 +3610,12 @@ "node": ">=12" } }, + "node_modules/d3-binarytree": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d3-binarytree/-/d3-binarytree-1.0.2.tgz", + "integrity": "sha512-cElUNH+sHu95L04m92pG73t2MEJXKu+GeKUN1TJkFsu93E5W8E9Sc3kHEGJKgenGvj19m6upSn2EunvMgMD2Yw==", + "license": "MIT" + }, "node_modules/d3-brush": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", @@ -3719,6 +3759,22 @@ "node": ">=12" } }, + "node_modules/d3-force-3d": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/d3-force-3d/-/d3-force-3d-3.0.6.tgz", + "integrity": "sha512-4tsKHUPLOVkyfEffZo1v6sFHvGFwAIIjt/W8IThbp08DYAsXZck+2pSHEG5W1+gQgEvFLdZkYvmJAbRM2EzMnA==", + "license": "MIT", + "dependencies": { + "d3-binarytree": "1", + "d3-dispatch": "1 - 3", + "d3-octree": "1", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/d3-format": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", @@ -3761,6 +3817,12 @@ "node": ">=12" } }, + "node_modules/d3-octree": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-octree/-/d3-octree-1.1.0.tgz", + "integrity": "sha512-F8gPlqpP+HwRPMO/8uOu5wjH110+6q4cgJvgJT6vlpy3BEaDIKlTZrgHKZSp/i1InRpVfh4puY/kvL6MxK930A==", + "license": "MIT" + }, "node_modules/d3-path": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", @@ -4909,6 +4971,20 @@ "dev": true, "license": "ISC" }, + "node_modules/float-tooltip": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/float-tooltip/-/float-tooltip-1.7.5.tgz", + "integrity": "sha512-/kXzuDnnBqyyWyhDMH7+PfP8J/oXiAavGzcRxASOMRHFuReDtofizLLJsf7nnDLAfEaMW4pVWaXrAjtnglpEkg==", + "license": "MIT", + "dependencies": { + "d3-selection": "2 - 3", + "kapsule": "^1.16", + "preact": "10" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/for-each": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", @@ -4925,6 +5001,32 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/force-graph": { + "version": "1.51.1", + "resolved": "https://registry.npmjs.org/force-graph/-/force-graph-1.51.1.tgz", + "integrity": "sha512-uEEX8iRzgq1IKRISOw6RrB2RLMhcI25xznQYrCTVvxZHZZ+A2jH6qIolYuwavVxAMi64pFp2yZm4KFVdD993cg==", + "license": "MIT", + "dependencies": { + "@tweenjs/tween.js": "18 - 25", + "accessor-fn": "1", + "bezier-js": "3 - 6", + "canvas-color-tracker": "^1.3", + "d3-array": "1 - 3", + "d3-drag": "2 - 3", + "d3-force-3d": "2 - 3", + "d3-scale": "1 - 4", + "d3-scale-chromatic": "1 - 3", + "d3-selection": "2 - 3", + "d3-zoom": "2 - 3", + "float-tooltip": "^1.7", + "index-array-by": "1", + "kapsule": "^1.16", + "lodash-es": "4" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/format": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", @@ -5341,6 +5443,15 @@ "node": ">=0.8.19" } }, + "node_modules/index-array-by": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/index-array-by/-/index-array-by-1.4.2.tgz", + "integrity": "sha512-SP23P27OUKzXWEC/TOyWlwLviofQkCSCKONnc62eItjp69yCZZPqDQtr3Pw5gJDnPeUMqExmKydNZaJO0FU9pw==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", @@ -5935,6 +6046,18 @@ "node": ">=4.0" } }, + "node_modules/kapsule": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/kapsule/-/kapsule-1.16.3.tgz", + "integrity": "sha512-4+5mNNf4vZDSwPhKprKwz3330iisPrb08JyMgbsdFrimBCKNHecua/WBwvVg3n7vwx0C1ARjfhwIpbrbd9n5wg==", + "license": "MIT", + "dependencies": { + "lodash-es": "4" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -6789,6 +6912,16 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "license": "MIT" }, + "node_modules/preact": { + "version": "10.28.4", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.28.4.tgz", + "integrity": "sha512-uKFfOHWuSNpRFVTnljsCluEFq57OKT+0QdOiQo8XWnQ/pSvg7OpX5eNOejELXJMWy+BwM2nobz0FkvzmnpCNsQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -7860,6 +7993,12 @@ "node": ">=0.8" } }, + "node_modules/tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", From 665039b64967ee84ed8201590e2fdb5d21ddf30d Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Thu, 26 Feb 2026 14:27:51 +0200 Subject: [PATCH 175/189] fix playwright ci sharding --- .github/workflows/playwright.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 7de5dea7..6a94c07c 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -36,7 +36,7 @@ jobs: run: | npm install npm run build - NEXTAUTH_SECRET=SECRET npm start & npx playwright test --reporter=dot,list + NEXTAUTH_SECRET=SECRET npm start & npx playwright test --shard=${{ matrix.shard }}/2 --reporter=dot,list - name: Ensure required directories exist run: | mkdir -p playwright-report From c68bae579c18fdab16151741407d781c4f27194f Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:56:42 +0200 Subject: [PATCH 176/189] fix search Bar tests --- e2e/logic/POM/codeGraph.ts | 25 +++++++++++++++++++++---- e2e/tests/searchBar.spec.ts | 11 +++++------ 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index e339c61c..dd961f56 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -103,7 +103,11 @@ export default class CodeGraph extends BasePage { } private get searchBarList(): Locator { - return this.scopedLocator("//div[@data-name='search-bar-list']"); + return this.page.locator('div[data-name="search-bar-list"]'); + } + + private get searchBarListFirstButtonInput(): Locator { + return this.searchBarList.locator("button").first().locator('div p').first(); } /* Chat Locators */ @@ -245,8 +249,12 @@ export default class CodeGraph extends BasePage { return this.scopedLocator(`//div[@data-name='node-details-panel']//button[@title='Copy src to clipboard']`); } + private get canvasTooltip(): Locator { + return this.page.locator('.float-tooltip-kap').first(); + } + private get nodeToolTip(): (node: string) => Locator { - return (node: string) => this.page.locator(`.float-tooltip-kap:has-text("${node}")`); + return (node: string) => this.page.locator('.float-tooltip-kap').filter({ hasText: node }); } private get downloadImageBtn(): Locator { @@ -435,8 +443,12 @@ export default class CodeGraph extends BasePage { await button.click(); } - async getSearchBarInputValue(): Promise { - return await this.searchBarInput.inputValue(); + async getSearchBarInputValue(): Promise { + let res: string | null = null; + await interactWhenVisible(this.searchBarListFirstButtonInput, async (el) => { + res = (await el.innerText())?.trim() ?? null; + }, 'searchBarListFirstButtonInput'); + return res; } async scrollToBottomInSearchBarList(): Promise { @@ -698,6 +710,11 @@ export default class CodeGraph extends BasePage { return await waitForElementToBeVisible(this.nodeToolTip(node)); } + async getNodeToolTipContent(): Promise { + await waitForElementToBeVisible(this.canvasTooltip); + return (await this.canvasTooltip.innerText()).trim(); + } + async getGraphDetails(): Promise { await this.canvasElementBeforeGraphSelection.waitFor({ state: 'detached' }); return await this.waitForGraphData(); diff --git a/e2e/tests/searchBar.spec.ts b/e2e/tests/searchBar.spec.ts index 97043add..ff788133 100644 --- a/e2e/tests/searchBar.spec.ts +++ b/e2e/tests/searchBar.spec.ts @@ -23,7 +23,6 @@ test.describe("search bar tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPHRAG_SDK); await codeGraph.fillSearchBar(searchInput); - await delay(1000); const textList = await codeGraph.getSearchBarElementsText(); textList.forEach((text) => { expect(text.toLowerCase()).toContain(searchInput); @@ -36,7 +35,6 @@ test.describe("search bar tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPHRAG_SDK); await codeGraph.fillSearchBar(searchInput); - await codeGraph.selectSearchBarOptionBtn("1"); expect(await codeGraph.getSearchBarInputValue()).toBe( completedSearchInput ); @@ -58,8 +56,8 @@ test.describe("search bar tests", () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPHRAG_SDK); await codeGraph.fillSearchBar(character); - await delay(1000); - expect((await codeGraph.getSearchBarInputValue()).includes(character)).toBe(expectedRes); + const res = await codeGraph.getSearchBarInputValue(); + expect(res !== null && res.includes(character)).toBe(expectedRes); }); }); @@ -76,7 +74,7 @@ test.describe("search bar tests", () => { }) nodes.forEach(({nodeName})=> { - test(`Verify canvas focuses on node ${nodeName} after search`, async () => {//here + test(`Verify canvas focuses on node ${nodeName} after search`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await browser.setPageToFullScreen(); await codeGraph.selectGraph(GRAPHRAG_SDK); @@ -85,7 +83,8 @@ test.describe("search bar tests", () => { await codeGraph.selectSearchBarOptionBtn("1"); await codeGraph.waitForCanvasAnimationToEnd(); await codeGraph.rightClickAtCanvasCenter(); - expect(await codeGraph.getNodeDetailsHeader()).toContain(nodeName.toUpperCase()); + expect(await codeGraph.getNodeToolTipContent()).toContain(nodeName); + }); }) }) \ No newline at end of file From de3dfd90239c4db7272e696a46fd54e8d0698026 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Thu, 26 Feb 2026 17:06:44 +0200 Subject: [PATCH 177/189] update @falkordb/canvas dependency to version 0.0.41 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 565aff53..c3a5dc05 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "code-graph", "version": "0.2.0", "dependencies": { - "@falkordb/canvas": "^0.0.40", + "@falkordb/canvas": "^0.0.41", "@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dropdown-menu": "^2.1.6", @@ -251,9 +251,9 @@ } }, "node_modules/@falkordb/canvas": { - "version": "0.0.40", - "resolved": "https://registry.npmjs.org/@falkordb/canvas/-/canvas-0.0.40.tgz", - "integrity": "sha512-sEIl10QHUXT5oGXkdLxY8saxStVQSxKfYd2THxJ4bjR77eq9L+OI8KYY5WRunX3UiZhfPiOy9PLaHHq0IuM8jg==", + "version": "0.0.41", + "resolved": "https://registry.npmjs.org/@falkordb/canvas/-/canvas-0.0.41.tgz", + "integrity": "sha512-r2DC2Mo9naASr3DDmVKCQVY/S50Hn2bGlmKaFxDRFcn5btiuuvPBqJ3krtC+uz5ZPmad8EoXRRlcQ6KwKJhUZw==", "license": "MIT", "dependencies": { "d3": "^7.9.0", diff --git a/package.json b/package.json index 646de52f..cd22ff9a 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@falkordb/canvas": "^0.0.40", + "@falkordb/canvas": "^0.0.41", "@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dropdown-menu": "^2.1.6", From 519e88d48ee78ce7adbab95c0860a6f007e714b8 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Thu, 26 Feb 2026 17:13:09 +0200 Subject: [PATCH 178/189] fix search tests --- e2e/config/testData.ts | 3 ++- e2e/logic/POM/codeGraph.ts | 10 ++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/e2e/config/testData.ts b/e2e/config/testData.ts index cdc91b81..0463eeee 100644 --- a/e2e/config/testData.ts +++ b/e2e/config/testData.ts @@ -11,7 +11,8 @@ const categorizeCharacters = (characters: string[], expectedRes: boolean): { cha export const specialCharacters: { character: string; expectedRes: boolean }[] = [ ...categorizeCharacters(['%', '*', '(', ')', '-', '[', ']', '{', '}', ';', ':', '"', '|', '~'], false), - ...categorizeCharacters(['!', '@', '$', '^', '_', '=', '+', "'", ',', '.', '<', '>', '/', '?', '\\', '`', '&', '#'], true) + ...categorizeCharacters(['!', '@', '$', '^', '=', '+', "'", ',', '<', '>', '/', '?', '\\', '`', '&', '#'], false), + ...categorizeCharacters(['_', '.'], true) ]; export const nodesPath: { firstNode: string; secondNode: string }[] = [ diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index dd961f56..427f6fb6 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -103,7 +103,7 @@ export default class CodeGraph extends BasePage { } private get searchBarList(): Locator { - return this.page.locator('div[data-name="search-bar-list"]'); + return this.scopedLocator('div[data-name="search-bar-list"]'); } private get searchBarListFirstButtonInput(): Locator { @@ -444,11 +444,9 @@ export default class CodeGraph extends BasePage { } async getSearchBarInputValue(): Promise { - let res: string | null = null; - await interactWhenVisible(this.searchBarListFirstButtonInput, async (el) => { - res = (await el.innerText())?.trim() ?? null; - }, 'searchBarListFirstButtonInput'); - return res; + const isVisible = await waitForElementToBeVisible(this.searchBarListFirstButtonInput); + if (!isVisible) return null; + return (await this.searchBarListFirstButtonInput.innerText())?.trim() ?? null; } async scrollToBottomInSearchBarList(): Promise { From d9609cddd212f7d9d886e6b8697c1507cc892584 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Sat, 28 Feb 2026 21:57:40 +0200 Subject: [PATCH 179/189] fix pom --- e2e/logic/POM/codeGraph.ts | 47 +++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 427f6fb6..09ff4243 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -479,10 +479,9 @@ export default class CodeGraph extends BasePage { } async clickOnRemoveNodeViaElementMenu(): Promise { - const button = this.elementMenuButton("Remove"); - const isVisible = await waitForElementToBeVisible(button); - if (!isVisible) throw new Error("'Remove' button is not visible!"); - await button.click(); + await interactWhenVisible( + this.elementMenuButton("Remove"), (el) => el.click(), 'Remove button' + ); } async nodeClick(x: number, y: number): Promise { @@ -546,10 +545,9 @@ export default class CodeGraph extends BasePage { } async clickOnViewNode(): Promise { - const button = this.elementMenuButton("View Node"); - const isButtonVisible = await waitForElementToBeVisible(button); - if (!isButtonVisible) throw new Error("'View Node' button is not visible!"); - await button.click(); + await interactWhenVisible( + this.elementMenuButton("View Node"), (el) => el.click(), 'View Node button' + ); } async getNodeDetailsHeader(): Promise { @@ -582,10 +580,9 @@ export default class CodeGraph extends BasePage { } async clickOnCopyToClipboard(): Promise { - const button = this.elementMenuButton("Copy src to clipboard"); - const isVisible = await waitForElementToBeVisible(button); - if (!isVisible) throw new Error("View Node button is not visible!"); - await button.click(); + await interactWhenVisible( + this.elementMenuButton("Copy src to clipboard"), (el) => el.click(), 'Copy src to clipboard button' + ); return await this.page.evaluate(() => navigator.clipboard.readText()); } @@ -594,14 +591,12 @@ export default class CodeGraph extends BasePage { } async getNodeDetailsPanelElements(): Promise { - const button = this.elementMenuButton("View Node"); - const isVisible = await waitForElementToBeVisible(button); - if (!isVisible) throw new Error("View Node button is not visible!"); - await button.click(); - - const isPanelVisible = await waitForElementToBeVisible(this.nodedetailsPanelElements.first()); - if (!isPanelVisible) throw new Error("Node details panel did not appear!"); - + await interactWhenVisible( + this.elementMenuButton("View Node"), (el) => el.click(), 'View Node button' + ); + await interactWhenVisible( + this.nodedetailsPanelElements.first(), async () => {}, 'Node details panel' + ); const elements = await this.nodedetailsPanelElements.all(); return Promise.all(elements.map(element => element.innerHTML())); } @@ -689,11 +684,21 @@ export default class CodeGraph extends BasePage { } async rightClickAtCanvasCenter(): Promise { + await this.waitForCanvasAnimationToEnd(); const boundingBox = await this.canvasElement.boundingBox(); if (!boundingBox) throw new Error('Canvas bounding box not found'); const centerX = boundingBox.x + boundingBox.width / 2; const centerY = boundingBox.y + boundingBox.height / 2; - await this.page.mouse.click(centerX, centerY, { button: 'right' }); + for (let attempt = 1; attempt <= 3; attempt++) { + await this.page.mouse.move(centerX, centerY); + await this.page.waitForTimeout(500); + await this.page.mouse.click(centerX, centerY, { button: 'right' }); + if (await this.elementMenu.isVisible()) { + return; + } + await this.page.waitForTimeout(1000); + } + throw new Error('Element menu not visible after right-clicking at canvas center'); } async hoverAtCanvasCenter(): Promise { From 34ad592949339eb20ca881b22ee105e3fcf4948d Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Sat, 28 Feb 2026 21:57:50 +0200 Subject: [PATCH 180/189] fix canvas tests --- e2e/tests/canvas.spec.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/e2e/tests/canvas.spec.ts b/e2e/tests/canvas.spec.ts index b3428bbd..de3662eb 100644 --- a/e2e/tests/canvas.spec.ts +++ b/e2e/tests/canvas.spec.ts @@ -73,10 +73,12 @@ test.describe("Canvas tests", () => { test(`Validate unhide node functionality after hiding a node in canvas for ${nodes[0].nodeName}`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); + await browser.setPageToFullScreen(); await codeGraph.selectGraph(GRAPHRAG_SDK); - const initialGraph = await codeGraph.getGraphNodes(); - const targetNode = findNodeByName(initialGraph, nodes[0].nodeName); - await codeGraph.nodeClick(targetNode.screenX, targetNode.screenY); + await codeGraph.fillSearchBar(nodes[0].nodeName); + await codeGraph.selectSearchBarOptionBtn("1"); + await codeGraph.waitForCanvasAnimationToEnd(); + await codeGraph.rightClickAtCanvasCenter(); await codeGraph.clickOnRemoveNodeViaElementMenu(); await codeGraph.clickOnUnhideNodesBtn(); const updatedGraph = await codeGraph.getGraphNodes(); From aead63149f27ff77d4035887070537149115ef41 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Sat, 28 Feb 2026 22:13:47 +0200 Subject: [PATCH 181/189] add interactWhenVisible for locators --- e2e/logic/POM/codeGraph.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 09ff4243..bba07ecd 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -464,17 +464,17 @@ export default class CodeGraph extends BasePage { /* Canvas functionality */ async clickZoomIn(): Promise { - await this.zoomInBtn.click(); + await interactWhenVisible(this.zoomInBtn, (el) => el.click(), 'Zoom In button'); await this.waitForCanvasAnimationToEnd(); } async clickZoomOut(): Promise { - await this.zoomOutBtn.click(); + await interactWhenVisible(this.zoomOutBtn, (el) => el.click(), 'Zoom Out button'); await this.waitForCanvasAnimationToEnd(); } async clickCenter(): Promise { - await this.centerBtn.click(); + await interactWhenVisible(this.centerBtn, (el) => el.click(), 'Center button'); await this.waitForCanvasAnimationToEnd(); } From dd8fd99013db7223dfd8cf8d073e9ca8d4cb5686 Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Sat, 28 Feb 2026 22:14:01 +0200 Subject: [PATCH 182/189] fix ci --- .github/workflows/playwright.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 6a94c07c..6fd5acdd 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -51,6 +51,6 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: failed-test-screenshots + name: failed-test-screenshots-shard-${{ matrix.shard }} path: playwright-report/artifacts/ retention-days: 30 From 998b2a353fc689a64a024f5b3db7049ef5552c9a Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Sat, 28 Feb 2026 22:24:59 +0200 Subject: [PATCH 183/189] Add interactWhenVisible safe waiting --- e2e/logic/POM/codeGraph.ts | 73 ++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 43 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index bba07ecd..af9e3d47 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -266,7 +266,7 @@ export default class CodeGraph extends BasePage { await this.page.waitForLoadState('networkidle'); const [newPage] = await Promise.all([ this.page.waitForEvent('popup'), - this.falkorDBLogo.click(), + interactWhenVisible(this.falkorDBLogo, (el) => el.click(), 'FalkorDB Logo'), ]); return newPage } @@ -275,15 +275,13 @@ export default class CodeGraph extends BasePage { await this.page.waitForLoadState('networkidle'); const [newPage] = await Promise.all([ this.page.waitForEvent('popup'), - this.navBaritem(navItem).click(), + interactWhenVisible(this.navBaritem(navItem), (el) => el.click(), `NavBar item: ${navItem}`), ]); return newPage } async clickCreateNewProjectBtn(): Promise { - const isVisible = await waitForElementToBeVisible(this.createNewProjectBtn); - if (!isVisible) throw new Error("'Create New Project' button is not visible!"); - await this.createNewProjectBtn.click(); + await interactWhenVisible(this.createNewProjectBtn, (el) => el.click(), 'Create New Project button'); } async isCreateNewProjectDialog(): Promise { @@ -291,7 +289,7 @@ export default class CodeGraph extends BasePage { } async clickOnTipBtn(): Promise { - await this.tipBtn.click(); + await interactWhenVisible(this.tipBtn, (el) => el.click(), 'Tip button'); } async isTipMenuVisible(): Promise { @@ -300,31 +298,27 @@ export default class CodeGraph extends BasePage { } async clickOnTipMenuCloseBtn(): Promise { - const isVisible = await waitForElementToBeVisible(this.tipMenuCloseBtn); - if (!isVisible) throw new Error("'Tip Menu Close' button is not visible!"); - await this.tipMenuCloseBtn.click(); + await interactWhenVisible(this.tipMenuCloseBtn, (el) => el.click(), 'Tip Menu Close button'); } /* Chat functionality */ async clickOnShowPathBtn(selection: string): Promise { - await this.showPathBtn(selection).click(); + await interactWhenVisible(this.showPathBtn(selection), (el) => el.click(), `Show Path button: ${selection}`); } async clickAskQuestionBtn(): Promise { - const isVisible = await waitForElementToBeVisible(this.askquestionBtn); - if (!isVisible) throw new Error("'Ask Question' button is not visible!"); - await this.askquestionBtn.click(); + await interactWhenVisible(this.askquestionBtn, (el) => el.click(), 'Ask Question button'); } async sendMessage(message: string) { await waitToBeEnabled(this.askquestionBtn); - await this.askquestionInput.fill(message); - await this.askquestionBtn.click(); + await interactWhenVisible(this.askquestionInput, (el) => el.fill(message), 'Ask question input'); + await interactWhenVisible(this.askquestionBtn, (el) => el.click(), 'Ask Question button'); } async clickOnLightBulbBtn(): Promise { - await this.lightbulbBtn.click(); + await interactWhenVisible(this.lightbulbBtn, (el) => el.click(), 'Light Bulb button'); } async getTextInLastChatElement(): Promise { @@ -366,8 +360,8 @@ export default class CodeGraph extends BasePage { } async insertInputForShowPath(inputNum: string, node: string): Promise { - await this.selectInputForShowPath(inputNum).fill(node); - await this.selectFirstPathOption(inputNum).click(); + await interactWhenVisible(this.selectInputForShowPath(inputNum), (el) => el.fill(node), `Path input ${inputNum}`); + await interactWhenVisible(this.selectFirstPathOption(inputNum), (el) => el.click(), `Path option ${inputNum}`); } async isNodeVisibleInLastChatPath(node: string): Promise { @@ -382,15 +376,14 @@ export default class CodeGraph extends BasePage { } async clickOnNotificationErrorCloseBtn(): Promise { - const isVisible = await waitForElementToBeVisible(this.notificationErrorCloseBtn); - if (!isVisible) throw new Error("Notification error close button is not visible!"); - await this.notificationErrorCloseBtn.click(); + await interactWhenVisible(this.notificationErrorCloseBtn, (el) => el.click(), 'Notification Error Close button'); } async selectAndGetQuestionInOptionsMenu(questionNumber: string): Promise { const question = this.selectQuestionInMenu(questionNumber); - await question.click(); - return await question.innerText(); + const text = await question.innerText(); + await interactWhenVisible(question, (el) => el.click(), `Question option ${questionNumber}`); + return text; } async getLastQuestionInChat(): Promise { @@ -401,35 +394,33 @@ export default class CodeGraph extends BasePage { /* CodeGraph functionality */ async selectGraph(graph: string | number): Promise { - await this.comboBoxbtn.click(); + await interactWhenVisible(this.comboBoxbtn, (el) => el.click(), 'ComboBox button'); if (typeof graph === 'number') { - await this.selectGraphInComboBoxById(graph.toString()).waitFor({ state: 'visible' }) - await this.selectGraphInComboBoxById(graph.toString()).click(); + await interactWhenVisible(this.selectGraphInComboBoxById(graph.toString()), (el) => el.click(), `Graph option ${graph}`); } else { - await this.selectGraphInComboBoxByName(graph).waitFor({ state: 'visible' }) - await this.selectGraphInComboBoxByName(graph).click(); + await interactWhenVisible(this.selectGraphInComboBoxByName(graph), (el) => el.click(), `Graph option ${graph}`); } await this.page.waitForTimeout(2000); // graph animation delay } async createProject(url: string): Promise { await this.clickCreateNewProjectBtn(); - await this.typeUrlInput.fill(url); - await this.createBtnInCreateProjectDialog.click(); + await interactWhenVisible(this.typeUrlInput, (el) => el.fill(url), 'URL input'); + await interactWhenVisible(this.createBtnInCreateProjectDialog, (el) => el.click(), 'Create button'); await this.createProjectWaitDialog.waitFor({ state: 'hidden' }); } async isGraphCreated(graph: string): Promise { - await this.comboBoxbtn.click(); + await interactWhenVisible(this.comboBoxbtn, (el) => el.click(), 'ComboBox button'); return await this.dialogCreatedGraphsList(graph).isVisible(); } async fillSearchBar(searchValue: string): Promise { - await this.searchBarInput.fill(searchValue); + await interactWhenVisible(this.searchBarInput, (el) => el.fill(searchValue), 'Search bar input'); } async getSearchAutoCompleteCount(): Promise { - await this.searchBarAutoCompleteOptions.first().waitFor({ state: 'visible' }); + await interactWhenVisible(this.searchBarAutoCompleteOptions.first(), async () => {}, 'Search auto-complete options'); return await this.searchBarAutoCompleteOptions.count(); } @@ -438,9 +429,7 @@ export default class CodeGraph extends BasePage { } async selectSearchBarOptionBtn(buttonNum: string): Promise { - const button = this.searchBarOptionBtn(buttonNum); - await button.waitFor({ state: "visible" }) - await button.click(); + await interactWhenVisible(this.searchBarOptionBtn(buttonNum), (el) => el.click(), `Search bar option ${buttonNum}`); } async getSearchBarInputValue(): Promise { @@ -501,12 +490,12 @@ export default class CodeGraph extends BasePage { async selectCodeGraphCheckbox(checkbox: string): Promise { - await this.codeGraphCheckbox(checkbox).click(); + await interactWhenVisible(this.codeGraphCheckbox(checkbox), (el) => el.click(), `Checkbox ${checkbox}`); } async clickOnClearGraphBtn(): Promise { await this.page.mouse.click(10, 10); - await this.clearGraphBtn.click(); + await interactWhenVisible(this.clearGraphBtn, (el) => el.click(), 'Clear Graph button'); } async clickOnUnhideNodesBtn(): Promise { @@ -563,7 +552,7 @@ export default class CodeGraph extends BasePage { } async clickOnNodeDetailsCloseBtn(): Promise { - await this.nodedetailsPanelcloseBtn.click(); + await interactWhenVisible(this.nodedetailsPanelcloseBtn, (el) => el.click(), 'Node Details Close button'); } async getMetricsPanelInfo(): Promise<{ nodes: string, edges: string }> { @@ -573,9 +562,7 @@ export default class CodeGraph extends BasePage { } async clickOnCopyToClipboardNodePanelDetails(): Promise { - const isButtonVisible = await waitForElementToBeVisible(this.copyToClipboardNodePanelDetails); - if (!isButtonVisible) throw new Error("'copy to clipboard button is not visible!"); - await this.copyToClipboardNodePanelDetails.click(); + await interactWhenVisible(this.copyToClipboardNodePanelDetails, (el) => el.click(), 'Copy to clipboard button'); return await this.page.evaluate(() => navigator.clipboard.readText()); } @@ -677,7 +664,7 @@ export default class CodeGraph extends BasePage { await this.page.waitForLoadState('networkidle'); const [download] = await Promise.all([ this.page.waitForEvent('download'), - this.downloadImageBtn.click(), + interactWhenVisible(this.downloadImageBtn, (el) => el.click(), 'Download Image button'), ]); return download; From 6af8c27c97469c87c5648037f36206bc8e2ed022 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Mon, 2 Mar 2026 14:53:12 +0200 Subject: [PATCH 184/189] Update version to 0.3.0 and refactor components for improved functionality and performance --- app/components/chat.tsx | 2 +- app/components/dataPanel.tsx | 1 - app/components/graphView.tsx | 10 ++++++++-- app/components/model.ts | 4 ++++ app/globals.css | 9 --------- app/page.tsx | 18 +++++++++--------- package-lock.json | 4 ++-- package.json | 2 +- 8 files changed, 25 insertions(+), 25 deletions(-) diff --git a/app/components/chat.tsx b/app/components/chat.tsx index ff99e169..a01da514 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -97,7 +97,7 @@ export function Chat({ messages, setMessages, query, setQuery, selectedPath, set if (!canvas) return setSelectedPath(prev => { if (prev) { - if (isPathResponse && paths.some((path) => [...path.nodes, ...path.links].every((e: any) => [...prev.nodes, ...prev.links].some((e: any) => e.id === e.id)))) { + if (isPathResponse && paths.some((path) => [...path.nodes, ...path.links].every((e: any) => [...prev.nodes, ...prev.links].some((el: any) => el.id === e.id)))) { graph.getElements().forEach(link => { const { id } = link diff --git a/app/components/dataPanel.tsx b/app/components/dataPanel.tsx index b1d84e38..4a50434f 100644 --- a/app/components/dataPanel.tsx +++ b/app/components/dataPanel.tsx @@ -18,7 +18,6 @@ const excludedProperties = [ "expand", "collapsed", "isPath", - "isPathSelected", "visible", "index", "curve", diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index aefda794..9ea3a2fe 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -164,7 +164,10 @@ export default function GraphView({ }, [zoomedNodes, cooldownTicks, canvasRef]) const nodeCanvasObject = useCallback((node: GraphNode, ctx: CanvasRenderingContext2D) => { - if (!node.x || !node.y) return + if (node.x === undefined || node.y === undefined) { + node.x = 0; + node.y = 0; + } const isHovered = !!hoverElement && !('source' in hoverElement) && hoverElement.id === node.id const isSelected = selectedObjects.some(obj => obj.id === node.id) || selectedObj?.id === node.id @@ -231,7 +234,10 @@ export default function GraphView({ }, [selectedObj, selectedObjects, isPathResponse, hoverElement]) const nodePointerAreaPaint = useCallback((node: GraphNode, color: string, ctx: CanvasRenderingContext2D) => { - if (!node.x || !node.y) return + if (node.x === undefined || node.y === undefined) { + node.x = 0; + node.y = 0; + } ctx.fillStyle = color; ctx.beginPath(); diff --git a/app/components/model.ts b/app/components/model.ts index 61626443..7253fa26 100644 --- a/app/components/model.ts +++ b/app/components/model.ts @@ -210,6 +210,8 @@ export class Graph { } this.nodesMap.set(edgeData.src_node, source) + this.elements.nodes.push(source) + newElements.nodes.push(source) } if (!target) { @@ -227,6 +229,8 @@ export class Graph { } } this.nodesMap.set(edgeData.dest_node, target) + this.elements.nodes.push(target) + newElements.nodes.push(target) } let label = this.labelsMap.get(edgeData.relation) diff --git a/app/globals.css b/app/globals.css index 26324540..1a377faf 100644 --- a/app/globals.css +++ b/app/globals.css @@ -127,13 +127,4 @@ ::-webkit-scrollbar-thumb:hover { background-color: #a8bbbf; -} - -@layer base { - * { - @apply border-border; - } - body { - @apply bg-background text-foreground; - } } \ No newline at end of file diff --git a/app/page.tsx b/app/page.tsx index f8f465c5..3a5c91de 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -368,7 +368,7 @@ export default function Home() {
- + FalkorDB

@@ -376,15 +376,15 @@ export default function Home() {

    - +

    Main Website

    - +

    Github

    - +

    Discord

    @@ -534,7 +534,7 @@ export default function Home() {
- + FalkorDB