-
-
Notifications
You must be signed in to change notification settings - Fork 54
Expand file tree
/
Copy pathRoutesTab.tsx
More file actions
138 lines (131 loc) · 4.86 KB
/
RoutesTab.tsx
File metadata and controls
138 lines (131 loc) · 4.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import { type MouseEvent, useEffect, useState } from "react"
import { useMatches, useNavigate } from "react-router"
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "../components/Accordion.js"
import { NewRouteForm } from "../components/NewRouteForm.js"
import { useDetachedWindowControls, useSettingsContext } from "../context/useRDTContext.js"
import { setRouteInLocalStorage } from "../hooks/detached/useListenToRouteChange.js"
import { type ExtendedRoute, constructRoutePath, createExtendedRoutes } from "../utils/routing.js"
import { createRouteTree } from "../utils/sanitize.js"
import clsx from "clsx"
import Tree from "react-d3-tree"
import { RouteInfo } from "../components/RouteInfo.js"
import { RouteNode } from "../components/RouteNode.js"
import { RouteToggle } from "../components/RouteToggle.js"
const RoutesTab = () => {
const matches = useMatches()
const navigate = useNavigate()
const activeRoutes = matches.map((match) => match.id)
const { settings } = useSettingsContext()
const { routeWildcards, routeViewMode } = settings
const { detachedWindow } = useDetachedWindowControls()
const [activeRoute, setActiveRoute] = useState<ExtendedRoute | null>(null)
const [routes] = useState<ExtendedRoute[]>(createExtendedRoutes() as ExtendedRoute[])
const [treeRoutes, setTreeRoutes] = useState(createRouteTree(window.__reactRouterManifest?.routes))
const isTreeView = routeViewMode === "tree"
const openNewRoute = (path: string) => (e?: MouseEvent<HTMLDivElement | HTMLButtonElement>) => {
e?.preventDefault()
navigate(path)
if (detachedWindow) {
setRouteInLocalStorage(path)
}
}
useEffect(function fetchAllRoutesOnMount() {
import.meta.hot?.send("routes-info")
const cb = (event: any) => {
const parsed = JSON.parse(event)
const data = parsed.data as Record<string, any>[]
const routeObject: Record<string, any> = {}
for (const route of data) {
routeObject[route.id] = route
}
routeObject.root = window.__reactRouterManifest?.routes?.root
setTreeRoutes(createRouteTree(routeObject))
}
import.meta.hot?.on("routes-info", cb)
return () => {
import.meta.hot?.off("routes-info", cb)
}
}, [])
return (
<div className={clsx("relative h-full w-full ", !isTreeView && "pt-8")}>
<RouteToggle />
{isTreeView ? (
<div className="flex h-full w-full">
<Tree
translate={{ x: window.innerWidth / 2 - (isTreeView && activeRoute ? 0 : 0), y: 30 }}
pathClassFunc={(link) =>
activeRoutes.includes((link.target.data.attributes as any).id)
? "stroke-yellow-500"
: window.__reactRouterManifest?.routes?.[link.target.data.attributes.id]
? "stroke-gray-400"
: "stroke-gray-400/20"
}
renderCustomNodeElement={(props) =>
RouteNode({
...props,
routeWildcards,
setActiveRoute,
activeRoutes,
navigate,
})
}
orientation="vertical"
data={treeRoutes}
/>
{activeRoute && (
<RouteInfo
openNewRoute={openNewRoute}
onClose={() => setActiveRoute(null)}
route={activeRoute}
className="w-[600px] border-l border-l-slate-800 p-2 px-4"
/>
)}
</div>
) : (
<Accordion className="h-full w-full overflow-y-auto pr-4" type="single" collapsible>
{
<AccordionItem value="add-new">
<AccordionTrigger className="text-white">
<span className="text-lg font-semibold">Add a new route to the project</span>
</AccordionTrigger>
<AccordionContent>
<NewRouteForm />
</AccordionContent>
</AccordionItem>
}
<div className="py-2">
<span className="text-lg font-semibold">Project routes</span>
<hr className="mt-2 border-gray-400" />
</div>
{routes?.map((route) => {
const { path, pathToOpen } = constructRoutePath(route, routeWildcards)
return (
<AccordionItem key={route.id} value={route.id}>
<AccordionTrigger>
<div className="justify-center flex-wrap text-white flex px-3 lg:px-0 flex-col lg:flex-row w-full items-start lg:items-center gap-1 ">
<span className="text-gray-500" /> {route.url}{" "}
<div className="lg:ml-auto flex-wrap flex items-center gap-2">
<span className=" text-left text-xs text-gray-500">Url: "{pathToOpen}"</span>
{/* biome-ignore lint/a11y/useKeyWithClickEvents: <explanation> */}
<div
title={pathToOpen}
className="mr-2 whitespace-nowrap rounded border border-gray-400 px-2 py-1 text-sm"
onClick={openNewRoute(path)}
>
Open in browser
</div>
</div>
</div>
</AccordionTrigger>
<AccordionContent>
<RouteInfo openNewRoute={openNewRoute} route={route} />
</AccordionContent>
</AccordionItem>
)
})}
</Accordion>
)}
</div>
)
}
export { RoutesTab }