@tanstack/router-devtools 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/dist/cjs/Explorer.cjs +246 -0
  2. package/dist/cjs/Explorer.cjs.map +1 -0
  3. package/dist/cjs/devtools.cjs +1150 -0
  4. package/dist/cjs/devtools.cjs.map +1 -0
  5. package/dist/cjs/index.cjs +6 -0
  6. package/dist/cjs/index.cjs.map +1 -0
  7. package/dist/cjs/styledComponents.cjs +93 -0
  8. package/dist/cjs/styledComponents.cjs.map +1 -0
  9. package/dist/cjs/theme.cjs +28 -0
  10. package/dist/cjs/theme.cjs.map +1 -0
  11. package/dist/cjs/useLocalStorage.cjs +45 -0
  12. package/dist/cjs/useLocalStorage.cjs.map +1 -0
  13. package/dist/cjs/useMediaQuery.cjs +27 -0
  14. package/dist/cjs/useMediaQuery.cjs.map +1 -0
  15. package/dist/cjs/utils.cjs +110 -0
  16. package/dist/cjs/utils.cjs.map +1 -0
  17. package/dist/esm/Explorer.d.ts +53 -0
  18. package/dist/esm/Explorer.js +229 -0
  19. package/dist/esm/Explorer.js.map +1 -0
  20. package/dist/esm/devtools.d.ts +65 -0
  21. package/dist/esm/devtools.js +1150 -0
  22. package/{build/cjs → dist/esm}/devtools.js.map +1 -1
  23. package/dist/esm/index.d.ts +1 -0
  24. package/dist/esm/index.js +6 -0
  25. package/{build/cjs → dist/esm}/index.js.map +1 -1
  26. package/dist/esm/styledComponents.d.ts +7 -0
  27. package/dist/esm/styledComponents.js +93 -0
  28. package/{build/cjs → dist/esm}/styledComponents.js.map +1 -1
  29. package/dist/esm/theme.d.ts +34 -0
  30. package/dist/esm/theme.js +28 -0
  31. package/dist/esm/theme.js.map +1 -0
  32. package/dist/esm/useLocalStorage.d.ts +1 -0
  33. package/dist/esm/useLocalStorage.js +46 -0
  34. package/dist/esm/useLocalStorage.js.map +1 -0
  35. package/dist/esm/useMediaQuery.d.ts +1 -0
  36. package/dist/esm/useMediaQuery.js +28 -0
  37. package/{build/cjs → dist/esm}/useMediaQuery.js.map +1 -1
  38. package/dist/esm/utils.d.ts +23 -0
  39. package/dist/esm/utils.js +110 -0
  40. package/{build/cjs → dist/esm}/utils.js.map +1 -1
  41. package/package.json +40 -21
  42. package/build/cjs/Explorer.js +0 -218
  43. package/build/cjs/Explorer.js.map +0 -1
  44. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js +0 -29
  45. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js.map +0 -1
  46. package/build/cjs/devtools.js +0 -828
  47. package/build/cjs/index.js +0 -19
  48. package/build/cjs/styledComponents.js +0 -76
  49. package/build/cjs/theme.js +0 -45
  50. package/build/cjs/theme.js.map +0 -1
  51. package/build/cjs/useLocalStorage.js +0 -54
  52. package/build/cjs/useLocalStorage.js.map +0 -1
  53. package/build/cjs/useMediaQuery.js +0 -54
  54. package/build/cjs/utils.js +0 -131
  55. package/build/esm/index.js +0 -1265
  56. package/build/esm/index.js.map +0 -1
  57. package/build/stats-html.html +0 -4838
  58. package/build/stats-react.json +0 -706
  59. package/build/umd/index.development.js +0 -1598
  60. package/build/umd/index.development.js.map +0 -1
  61. package/build/umd/index.production.js +0 -22
  62. package/build/umd/index.production.js.map +0 -1
  63. /package/{build/types/Explorer.d.ts → dist/cjs/Explorer.d.cts} +0 -0
  64. /package/{build/types/devtools.d.ts → dist/cjs/devtools.d.cts} +0 -0
  65. /package/{build/types/index.d.ts → dist/cjs/index.d.cts} +0 -0
  66. /package/{build/types/styledComponents.d.ts → dist/cjs/styledComponents.d.cts} +0 -0
  67. /package/{build/types/theme.d.ts → dist/cjs/theme.d.cts} +0 -0
  68. /package/{build/types/useLocalStorage.d.ts → dist/cjs/useLocalStorage.d.cts} +0 -0
  69. /package/{build/types/useMediaQuery.d.ts → dist/cjs/useMediaQuery.d.cts} +0 -0
  70. /package/{build/types/utils.d.ts → dist/cjs/utils.d.cts} +0 -0
@@ -0,0 +1,1150 @@
1
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
+ import React__default from "react";
3
+ import { useRouter, useRouterState, invariant, trimPath } from "@tanstack/react-router";
4
+ import useLocalStorage from "./useLocalStorage.js";
5
+ import { useSafeState, useIsMounted, multiSortBy, getStatusColor, getRouteStatusColor } from "./utils.js";
6
+ import { Button, Panel, Code, ActivePanel } from "./styledComponents.js";
7
+ import { ThemeProvider, defaultTheme } from "./theme.js";
8
+ import Explorer from "./Explorer.js";
9
+ const isServer = typeof window === "undefined";
10
+ function Logo(props) {
11
+ return /* @__PURE__ */ jsxs(
12
+ "div",
13
+ {
14
+ ...props,
15
+ style: {
16
+ ...props.style ?? {},
17
+ display: "flex",
18
+ alignItems: "center",
19
+ flexDirection: "column",
20
+ fontSize: "0.8rem",
21
+ fontWeight: "bolder",
22
+ lineHeight: "1"
23
+ },
24
+ children: [
25
+ /* @__PURE__ */ jsx(
26
+ "div",
27
+ {
28
+ style: {
29
+ letterSpacing: "-0.05rem"
30
+ },
31
+ children: "TANSTACK"
32
+ }
33
+ ),
34
+ /* @__PURE__ */ jsx(
35
+ "div",
36
+ {
37
+ style: {
38
+ backgroundImage: "linear-gradient(to right, var(--tw-gradient-stops))",
39
+ // @ts-ignore
40
+ "--tw-gradient-from": "#84cc16",
41
+ "--tw-gradient-stops": "var(--tw-gradient-from), var(--tw-gradient-to)",
42
+ "--tw-gradient-to": "#10b981",
43
+ WebkitBackgroundClip: "text",
44
+ color: "transparent",
45
+ letterSpacing: "0.1rem",
46
+ marginRight: "-0.2rem"
47
+ },
48
+ children: "ROUTER"
49
+ }
50
+ )
51
+ ]
52
+ }
53
+ );
54
+ }
55
+ function TanStackRouterDevtools({
56
+ initialIsOpen,
57
+ panelProps = {},
58
+ closeButtonProps = {},
59
+ toggleButtonProps = {},
60
+ position = "bottom-left",
61
+ containerElement: Container = "footer",
62
+ router
63
+ }) {
64
+ const rootRef = React__default.useRef(null);
65
+ const panelRef = React__default.useRef(null);
66
+ const [isOpen, setIsOpen] = useLocalStorage(
67
+ "tanstackRouterDevtoolsOpen",
68
+ initialIsOpen
69
+ );
70
+ const [devtoolsHeight, setDevtoolsHeight] = useLocalStorage(
71
+ "tanstackRouterDevtoolsHeight",
72
+ null
73
+ );
74
+ const [isResolvedOpen, setIsResolvedOpen] = useSafeState(false);
75
+ const [isResizing, setIsResizing] = useSafeState(false);
76
+ const isMounted = useIsMounted();
77
+ const handleDragStart = (panelElement, startEvent) => {
78
+ if (startEvent.button !== 0)
79
+ return;
80
+ setIsResizing(true);
81
+ const dragInfo = {
82
+ originalHeight: (panelElement == null ? void 0 : panelElement.getBoundingClientRect().height) ?? 0,
83
+ pageY: startEvent.pageY
84
+ };
85
+ const run = (moveEvent) => {
86
+ const delta = dragInfo.pageY - moveEvent.pageY;
87
+ const newHeight = (dragInfo == null ? void 0 : dragInfo.originalHeight) + delta;
88
+ setDevtoolsHeight(newHeight);
89
+ if (newHeight < 70) {
90
+ setIsOpen(false);
91
+ } else {
92
+ setIsOpen(true);
93
+ }
94
+ };
95
+ const unsub = () => {
96
+ setIsResizing(false);
97
+ document.removeEventListener("mousemove", run);
98
+ document.removeEventListener("mouseUp", unsub);
99
+ };
100
+ document.addEventListener("mousemove", run);
101
+ document.addEventListener("mouseup", unsub);
102
+ };
103
+ React__default.useEffect(() => {
104
+ setIsResolvedOpen(isOpen ?? false);
105
+ }, [isOpen, isResolvedOpen, setIsResolvedOpen]);
106
+ React__default.useEffect(() => {
107
+ const ref = panelRef.current;
108
+ if (ref) {
109
+ const handlePanelTransitionStart = () => {
110
+ if (ref && isResolvedOpen) {
111
+ ref.style.visibility = "visible";
112
+ }
113
+ };
114
+ const handlePanelTransitionEnd = () => {
115
+ if (ref && !isResolvedOpen) {
116
+ ref.style.visibility = "hidden";
117
+ }
118
+ };
119
+ ref.addEventListener("transitionstart", handlePanelTransitionStart);
120
+ ref.addEventListener("transitionend", handlePanelTransitionEnd);
121
+ return () => {
122
+ ref.removeEventListener("transitionstart", handlePanelTransitionStart);
123
+ ref.removeEventListener("transitionend", handlePanelTransitionEnd);
124
+ };
125
+ }
126
+ return;
127
+ }, [isResolvedOpen]);
128
+ React__default[isServer ? "useEffect" : "useLayoutEffect"](() => {
129
+ var _a, _b;
130
+ if (isResolvedOpen) {
131
+ const previousValue = (_b = (_a = rootRef.current) == null ? void 0 : _a.parentElement) == null ? void 0 : _b.style.paddingBottom;
132
+ const run = () => {
133
+ var _a2, _b2;
134
+ const containerHeight = (_a2 = panelRef.current) == null ? void 0 : _a2.getBoundingClientRect().height;
135
+ if ((_b2 = rootRef.current) == null ? void 0 : _b2.parentElement) {
136
+ rootRef.current.parentElement.style.paddingBottom = `${containerHeight}px`;
137
+ }
138
+ };
139
+ run();
140
+ if (typeof window !== "undefined") {
141
+ window.addEventListener("resize", run);
142
+ return () => {
143
+ var _a2;
144
+ window.removeEventListener("resize", run);
145
+ if (((_a2 = rootRef.current) == null ? void 0 : _a2.parentElement) && typeof previousValue === "string") {
146
+ rootRef.current.parentElement.style.paddingBottom = previousValue;
147
+ }
148
+ };
149
+ }
150
+ }
151
+ return;
152
+ }, [isResolvedOpen]);
153
+ const { style: panelStyle = {}, ...otherPanelProps } = panelProps;
154
+ const {
155
+ style: closeButtonStyle = {},
156
+ onClick: onCloseClick,
157
+ ...otherCloseButtonProps
158
+ } = closeButtonProps;
159
+ const {
160
+ style: toggleButtonStyle = {},
161
+ onClick: onToggleClick,
162
+ ...otherToggleButtonProps
163
+ } = toggleButtonProps;
164
+ if (!isMounted())
165
+ return null;
166
+ return /* @__PURE__ */ jsxs(Container, { ref: rootRef, className: "TanStackRouterDevtools", children: [
167
+ /* @__PURE__ */ jsxs(ThemeProvider, { theme: defaultTheme, children: [
168
+ /* @__PURE__ */ jsx(
169
+ TanStackRouterDevtoolsPanel,
170
+ {
171
+ ref: panelRef,
172
+ ...otherPanelProps,
173
+ router,
174
+ style: {
175
+ position: "fixed",
176
+ bottom: "0",
177
+ right: "0",
178
+ zIndex: 99999,
179
+ width: "100%",
180
+ height: devtoolsHeight ?? 500,
181
+ maxHeight: "90%",
182
+ boxShadow: "0 0 20px rgba(0,0,0,.3)",
183
+ borderTop: `1px solid ${defaultTheme.gray}`,
184
+ transformOrigin: "top",
185
+ // visibility will be toggled after transitions, but set initial state here
186
+ visibility: isOpen ? "visible" : "hidden",
187
+ ...panelStyle,
188
+ ...isResizing ? {
189
+ transition: `none`
190
+ } : { transition: `all .2s ease` },
191
+ ...isResolvedOpen ? {
192
+ opacity: 1,
193
+ pointerEvents: "all",
194
+ transform: `translateY(0) scale(1)`
195
+ } : {
196
+ opacity: 0,
197
+ pointerEvents: "none",
198
+ transform: `translateY(15px) scale(1.02)`
199
+ }
200
+ },
201
+ isOpen: isResolvedOpen,
202
+ setIsOpen,
203
+ handleDragStart: (e) => handleDragStart(panelRef.current, e)
204
+ }
205
+ ),
206
+ isResolvedOpen ? /* @__PURE__ */ jsx(
207
+ Button,
208
+ {
209
+ type: "button",
210
+ "aria-label": "Close TanStack Router Devtools",
211
+ ...otherCloseButtonProps,
212
+ onClick: (e) => {
213
+ setIsOpen(false);
214
+ onCloseClick && onCloseClick(e);
215
+ },
216
+ style: {
217
+ position: "fixed",
218
+ zIndex: 99999,
219
+ margin: ".5em",
220
+ bottom: 0,
221
+ ...position === "top-right" ? {
222
+ right: "0"
223
+ } : position === "top-left" ? {
224
+ left: "0"
225
+ } : position === "bottom-right" ? {
226
+ right: "0"
227
+ } : {
228
+ left: "0"
229
+ },
230
+ ...closeButtonStyle
231
+ },
232
+ children: "Close"
233
+ }
234
+ ) : null
235
+ ] }),
236
+ !isResolvedOpen ? /* @__PURE__ */ jsx(
237
+ "button",
238
+ {
239
+ type: "button",
240
+ ...otherToggleButtonProps,
241
+ "aria-label": "Open TanStack Router Devtools",
242
+ onClick: (e) => {
243
+ setIsOpen(true);
244
+ onToggleClick && onToggleClick(e);
245
+ },
246
+ style: {
247
+ appearance: "none",
248
+ background: "none",
249
+ border: 0,
250
+ padding: 0,
251
+ position: "fixed",
252
+ zIndex: 99999,
253
+ display: "inline-flex",
254
+ fontSize: "1.5em",
255
+ margin: ".5em",
256
+ cursor: "pointer",
257
+ width: "fit-content",
258
+ ...position === "top-right" ? {
259
+ top: "0",
260
+ right: "0"
261
+ } : position === "top-left" ? {
262
+ top: "0",
263
+ left: "0"
264
+ } : position === "bottom-right" ? {
265
+ bottom: "0",
266
+ right: "0"
267
+ } : {
268
+ bottom: "0",
269
+ left: "0"
270
+ },
271
+ ...toggleButtonStyle
272
+ },
273
+ children: /* @__PURE__ */ jsx(Logo, { "aria-hidden": true })
274
+ }
275
+ ) : null
276
+ ] });
277
+ }
278
+ function RouteComp({
279
+ route,
280
+ isRoot,
281
+ activeId,
282
+ setActiveId
283
+ }) {
284
+ var _a;
285
+ const routerState = useRouterState();
286
+ const matches = routerState.status === "pending" ? routerState.pendingMatches ?? [] : routerState.matches;
287
+ const match = routerState.matches.find((d) => d.routeId === route.id);
288
+ return /* @__PURE__ */ jsxs("div", { children: [
289
+ /* @__PURE__ */ jsxs(
290
+ "div",
291
+ {
292
+ role: "button",
293
+ "aria-label": `Open match details for ${route.id}`,
294
+ onClick: () => {
295
+ if (match) {
296
+ setActiveId(activeId === route.id ? "" : route.id);
297
+ }
298
+ },
299
+ style: {
300
+ display: "flex",
301
+ borderBottom: `solid 1px ${defaultTheme.grayAlt}`,
302
+ cursor: match ? "pointer" : "default",
303
+ alignItems: "center",
304
+ background: route.id === activeId ? "rgba(255,255,255,.1)" : void 0,
305
+ padding: ".25rem .5rem",
306
+ gap: ".5rem"
307
+ },
308
+ children: [
309
+ isRoot ? null : /* @__PURE__ */ jsx(
310
+ "div",
311
+ {
312
+ style: {
313
+ flex: "0 0 auto",
314
+ width: ".7rem",
315
+ height: ".7rem",
316
+ alignItems: "center",
317
+ justifyContent: "center",
318
+ fontWeight: "bold",
319
+ borderRadius: "100%",
320
+ transition: "all .2s ease-out",
321
+ background: getRouteStatusColor(matches, route, defaultTheme),
322
+ opacity: match ? 1 : 0.3
323
+ }
324
+ }
325
+ ),
326
+ /* @__PURE__ */ jsxs(
327
+ "div",
328
+ {
329
+ style: {
330
+ flex: "1 0 auto",
331
+ display: "flex",
332
+ justifyContent: "space-between",
333
+ alignItems: "center",
334
+ padding: isRoot ? "0 .25rem" : 0,
335
+ opacity: match ? 1 : 0.7,
336
+ fontSize: "0.7rem"
337
+ },
338
+ children: [
339
+ /* @__PURE__ */ jsxs(Code, { children: [
340
+ route.path || trimPath(route.id),
341
+ " "
342
+ ] }),
343
+ /* @__PURE__ */ jsxs(
344
+ "div",
345
+ {
346
+ style: {
347
+ display: "flex",
348
+ alignItems: "center",
349
+ gap: ".5rem"
350
+ },
351
+ children: [
352
+ match ? /* @__PURE__ */ jsx(Code, { style: { opacity: 0.3 }, children: match.id }) : null,
353
+ /* @__PURE__ */ jsx(AgeTicker, { match })
354
+ ]
355
+ }
356
+ )
357
+ ]
358
+ }
359
+ )
360
+ ]
361
+ }
362
+ ),
363
+ ((_a = route.children) == null ? void 0 : _a.length) ? /* @__PURE__ */ jsx(
364
+ "div",
365
+ {
366
+ style: {
367
+ marginLeft: isRoot ? 0 : "1rem",
368
+ borderLeft: isRoot ? "" : `solid 1px ${defaultTheme.grayAlt}`
369
+ },
370
+ children: [...route.children].sort((a, b) => {
371
+ return a.rank - b.rank;
372
+ }).map((r) => /* @__PURE__ */ jsx(
373
+ RouteComp,
374
+ {
375
+ route: r,
376
+ activeId,
377
+ setActiveId
378
+ },
379
+ r.id
380
+ ))
381
+ }
382
+ ) : null
383
+ ] });
384
+ }
385
+ const TanStackRouterDevtoolsPanel = React__default.forwardRef(function TanStackRouterDevtoolsPanel2(props, ref) {
386
+ var _a, _b, _c;
387
+ const {
388
+ isOpen = true,
389
+ setIsOpen,
390
+ handleDragStart,
391
+ router: userRouter,
392
+ ...panelProps
393
+ } = props;
394
+ const router = useRouter();
395
+ const routerState = useRouterState();
396
+ const matches = [
397
+ ...routerState.pendingMatches ?? [],
398
+ ...routerState.matches,
399
+ ...routerState.cachedMatches
400
+ ];
401
+ invariant(
402
+ router,
403
+ "No router was found for the TanStack Router Devtools. Please place the devtools in the <RouterProvider> component tree or pass the router instance to the devtools manually."
404
+ );
405
+ const [showMatches, setShowMatches] = useLocalStorage(
406
+ "tanstackRouterDevtoolsShowMatches",
407
+ true
408
+ );
409
+ const [activeId, setActiveId] = useLocalStorage(
410
+ "tanstackRouterDevtoolsActiveRouteId",
411
+ ""
412
+ );
413
+ const activeMatch = React__default.useMemo(
414
+ () => matches.find((d) => d.routeId === activeId || d.id === activeId),
415
+ [matches, activeId]
416
+ );
417
+ const hasSearch = Object.keys(routerState.location.search || {}).length;
418
+ const explorerState = {
419
+ ...router,
420
+ state: router.state
421
+ };
422
+ return /* @__PURE__ */ jsx(ThemeProvider, { theme: defaultTheme, children: /* @__PURE__ */ jsxs(Panel, { ref, className: "TanStackRouterDevtoolsPanel", ...panelProps, children: [
423
+ /* @__PURE__ */ jsx(
424
+ "style",
425
+ {
426
+ dangerouslySetInnerHTML: {
427
+ __html: `
428
+
429
+ .TanStackRouterDevtoolsPanel * {
430
+ scrollbar-color: ${defaultTheme.backgroundAlt} ${defaultTheme.gray};
431
+ }
432
+
433
+ .TanStackRouterDevtoolsPanel *::-webkit-scrollbar, .TanStackRouterDevtoolsPanel scrollbar {
434
+ width: 1em;
435
+ height: 1em;
436
+ }
437
+
438
+ .TanStackRouterDevtoolsPanel *::-webkit-scrollbar-track, .TanStackRouterDevtoolsPanel scrollbar-track {
439
+ background: ${defaultTheme.backgroundAlt};
440
+ }
441
+
442
+ .TanStackRouterDevtoolsPanel *::-webkit-scrollbar-thumb, .TanStackRouterDevtoolsPanel scrollbar-thumb {
443
+ background: ${defaultTheme.gray};
444
+ border-radius: .5em;
445
+ border: 3px solid ${defaultTheme.backgroundAlt};
446
+ }
447
+
448
+ .TanStackRouterDevtoolsPanel table {
449
+ width: 100%;
450
+ }
451
+
452
+ .TanStackRouterDevtoolsPanel table tr {
453
+ border-bottom: 2px dotted rgba(255, 255, 255, .2);
454
+ }
455
+
456
+ .TanStackRouterDevtoolsPanel table tr:last-child {
457
+ border-bottom: none
458
+ }
459
+
460
+ .TanStackRouterDevtoolsPanel table td {
461
+ padding: .25rem .5rem;
462
+ border-right: 2px dotted rgba(255, 255, 255, .05);
463
+ }
464
+
465
+ .TanStackRouterDevtoolsPanel table td:last-child {
466
+ border-right: none
467
+ }
468
+
469
+ `
470
+ }
471
+ }
472
+ ),
473
+ /* @__PURE__ */ jsx(
474
+ "div",
475
+ {
476
+ style: {
477
+ position: "absolute",
478
+ left: 0,
479
+ top: 0,
480
+ width: "100%",
481
+ height: "4px",
482
+ marginBottom: "-4px",
483
+ cursor: "row-resize",
484
+ zIndex: 1e5
485
+ },
486
+ onMouseDown: handleDragStart
487
+ }
488
+ ),
489
+ /* @__PURE__ */ jsxs(
490
+ "div",
491
+ {
492
+ style: {
493
+ flex: "1 1 500px",
494
+ minHeight: "40%",
495
+ maxHeight: "100%",
496
+ overflow: "auto",
497
+ borderRight: `1px solid ${defaultTheme.grayAlt}`,
498
+ display: "flex",
499
+ flexDirection: "column"
500
+ },
501
+ children: [
502
+ /* @__PURE__ */ jsxs(
503
+ "div",
504
+ {
505
+ style: {
506
+ display: "flex",
507
+ justifyContent: "start",
508
+ gap: "1rem",
509
+ padding: "1rem",
510
+ alignItems: "center",
511
+ background: defaultTheme.backgroundAlt
512
+ },
513
+ children: [
514
+ /* @__PURE__ */ jsx(Logo, { "aria-hidden": true }),
515
+ /* @__PURE__ */ jsx(
516
+ "div",
517
+ {
518
+ style: {
519
+ fontSize: "clamp(.8rem, 2vw, 1.3rem)",
520
+ fontWeight: "bold"
521
+ },
522
+ children: /* @__PURE__ */ jsx(
523
+ "span",
524
+ {
525
+ style: {
526
+ fontWeight: 100
527
+ },
528
+ children: "Devtools"
529
+ }
530
+ )
531
+ }
532
+ )
533
+ ]
534
+ }
535
+ ),
536
+ /* @__PURE__ */ jsx(
537
+ "div",
538
+ {
539
+ style: {
540
+ overflowY: "auto",
541
+ flex: "1"
542
+ },
543
+ children: /* @__PURE__ */ jsx(
544
+ "div",
545
+ {
546
+ style: {
547
+ padding: ".5em"
548
+ },
549
+ children: /* @__PURE__ */ jsx(
550
+ Explorer,
551
+ {
552
+ label: "Router",
553
+ value: Object.fromEntries(
554
+ multiSortBy(
555
+ Object.keys(explorerState),
556
+ [
557
+ "state",
558
+ "routesById",
559
+ "routesByPath",
560
+ "flatRoutes",
561
+ "options"
562
+ ].map((d) => (dd) => dd !== d)
563
+ ).map((key) => [key, explorerState[key]]).filter(
564
+ (d) => typeof d[1] !== "function" && ![
565
+ "__store",
566
+ "basepath",
567
+ "injectedHtml",
568
+ "subscribers",
569
+ "latestLoadPromise",
570
+ "navigateTimeout",
571
+ "resetNextScroll",
572
+ "tempLocationKey",
573
+ "latestLocation",
574
+ "routeTree",
575
+ "history"
576
+ ].includes(d[0])
577
+ )
578
+ ),
579
+ defaultExpanded: {
580
+ state: {},
581
+ context: {},
582
+ options: {}
583
+ },
584
+ filterSubEntries: (subEntries) => {
585
+ return subEntries.filter((d) => typeof d.value !== "function");
586
+ }
587
+ }
588
+ )
589
+ }
590
+ )
591
+ }
592
+ )
593
+ ]
594
+ }
595
+ ),
596
+ /* @__PURE__ */ jsxs(
597
+ "div",
598
+ {
599
+ style: {
600
+ flex: "1 1 500px",
601
+ minHeight: "40%",
602
+ maxHeight: "100%",
603
+ overflow: "auto",
604
+ borderRight: `1px solid ${defaultTheme.grayAlt}`,
605
+ display: "flex",
606
+ flexDirection: "column"
607
+ },
608
+ children: [
609
+ /* @__PURE__ */ jsxs(
610
+ "div",
611
+ {
612
+ style: {
613
+ flex: "1 1 auto",
614
+ overflowY: "auto"
615
+ },
616
+ children: [
617
+ /* @__PURE__ */ jsxs(
618
+ "div",
619
+ {
620
+ style: {
621
+ padding: ".5em",
622
+ background: defaultTheme.backgroundAlt,
623
+ position: "sticky",
624
+ top: 0,
625
+ zIndex: 1,
626
+ display: "flex",
627
+ alignItems: "center",
628
+ gap: ".5rem",
629
+ fontWeight: "bold"
630
+ },
631
+ children: [
632
+ "Pathname",
633
+ " ",
634
+ routerState.location.maskedLocation ? /* @__PURE__ */ jsx(
635
+ "div",
636
+ {
637
+ style: {
638
+ padding: ".1rem .5rem",
639
+ background: defaultTheme.warning,
640
+ color: "black",
641
+ borderRadius: ".5rem"
642
+ },
643
+ children: "Masked"
644
+ }
645
+ ) : null
646
+ ]
647
+ }
648
+ ),
649
+ /* @__PURE__ */ jsxs(
650
+ "div",
651
+ {
652
+ style: {
653
+ padding: ".5rem",
654
+ display: "flex",
655
+ gap: ".5rem",
656
+ alignItems: "center"
657
+ },
658
+ children: [
659
+ /* @__PURE__ */ jsx(
660
+ "code",
661
+ {
662
+ style: {
663
+ opacity: 0.6
664
+ },
665
+ children: routerState.location.pathname
666
+ }
667
+ ),
668
+ routerState.location.maskedLocation ? /* @__PURE__ */ jsx(
669
+ "code",
670
+ {
671
+ style: {
672
+ color: defaultTheme.warning,
673
+ fontWeight: "bold"
674
+ },
675
+ children: routerState.location.maskedLocation.pathname
676
+ }
677
+ ) : null
678
+ ]
679
+ }
680
+ ),
681
+ /* @__PURE__ */ jsxs(
682
+ "div",
683
+ {
684
+ style: {
685
+ padding: ".5em",
686
+ background: defaultTheme.backgroundAlt,
687
+ position: "sticky",
688
+ top: 0,
689
+ zIndex: 1,
690
+ display: "flex",
691
+ alignItems: "center",
692
+ justifyContent: "space-between",
693
+ gap: ".5rem",
694
+ fontWeight: "bold"
695
+ },
696
+ children: [
697
+ /* @__PURE__ */ jsxs(
698
+ "div",
699
+ {
700
+ style: {
701
+ display: "flex",
702
+ alignItems: "center",
703
+ gap: ".5rem"
704
+ },
705
+ children: [
706
+ /* @__PURE__ */ jsx(
707
+ "button",
708
+ {
709
+ type: "button",
710
+ onClick: () => {
711
+ setShowMatches(false);
712
+ },
713
+ disabled: !showMatches,
714
+ style: {
715
+ appearance: "none",
716
+ opacity: showMatches ? 0.5 : 1,
717
+ border: 0,
718
+ background: "transparent",
719
+ color: "inherit",
720
+ cursor: "pointer"
721
+ },
722
+ children: "Routes"
723
+ }
724
+ ),
725
+ "/",
726
+ /* @__PURE__ */ jsx(
727
+ "button",
728
+ {
729
+ type: "button",
730
+ onClick: () => {
731
+ setShowMatches(true);
732
+ },
733
+ disabled: showMatches,
734
+ style: {
735
+ appearance: "none",
736
+ opacity: !showMatches ? 0.5 : 1,
737
+ border: 0,
738
+ background: "transparent",
739
+ color: "inherit",
740
+ cursor: "pointer"
741
+ },
742
+ children: "Matches"
743
+ }
744
+ )
745
+ ]
746
+ }
747
+ ),
748
+ /* @__PURE__ */ jsx(
749
+ "div",
750
+ {
751
+ style: {
752
+ opacity: 0.3,
753
+ fontSize: "0.7rem",
754
+ fontWeight: "normal"
755
+ },
756
+ children: "age / staleTime / gcTime"
757
+ }
758
+ )
759
+ ]
760
+ }
761
+ ),
762
+ !showMatches ? /* @__PURE__ */ jsx(
763
+ RouteComp,
764
+ {
765
+ route: router.routeTree,
766
+ isRoot: true,
767
+ activeId,
768
+ setActiveId
769
+ }
770
+ ) : /* @__PURE__ */ jsx("div", { children: (routerState.status === "pending" ? routerState.pendingMatches ?? [] : routerState.matches).map((match, i) => {
771
+ return /* @__PURE__ */ jsxs(
772
+ "div",
773
+ {
774
+ role: "button",
775
+ "aria-label": `Open match details for ${match.id}`,
776
+ onClick: () => setActiveId(activeId === match.id ? "" : match.id),
777
+ style: {
778
+ display: "flex",
779
+ borderBottom: `solid 1px ${defaultTheme.grayAlt}`,
780
+ cursor: "pointer",
781
+ alignItems: "center",
782
+ background: match === activeMatch ? "rgba(255,255,255,.1)" : void 0
783
+ },
784
+ children: [
785
+ /* @__PURE__ */ jsx(
786
+ "div",
787
+ {
788
+ style: {
789
+ flex: "0 0 auto",
790
+ width: "1.3rem",
791
+ height: "1.3rem",
792
+ marginLeft: ".25rem",
793
+ background: getStatusColor(match, defaultTheme),
794
+ alignItems: "center",
795
+ justifyContent: "center",
796
+ fontWeight: "bold",
797
+ borderRadius: ".25rem",
798
+ transition: "all .2s ease-out"
799
+ }
800
+ }
801
+ ),
802
+ /* @__PURE__ */ jsx(
803
+ Code,
804
+ {
805
+ style: {
806
+ padding: ".5em",
807
+ fontSize: "0.7rem"
808
+ },
809
+ children: `${match.id}`
810
+ }
811
+ ),
812
+ /* @__PURE__ */ jsx(AgeTicker, { match })
813
+ ]
814
+ },
815
+ match.id || i
816
+ );
817
+ }) })
818
+ ]
819
+ }
820
+ ),
821
+ ((_a = routerState.cachedMatches) == null ? void 0 : _a.length) ? /* @__PURE__ */ jsxs(
822
+ "div",
823
+ {
824
+ style: {
825
+ flex: "1 1 auto",
826
+ overflowY: "auto",
827
+ maxHeight: "50%"
828
+ },
829
+ children: [
830
+ /* @__PURE__ */ jsxs(
831
+ "div",
832
+ {
833
+ style: {
834
+ padding: ".5em",
835
+ background: defaultTheme.backgroundAlt,
836
+ position: "sticky",
837
+ top: 0,
838
+ zIndex: 1,
839
+ display: "flex",
840
+ alignItems: "center",
841
+ justifyContent: "space-between",
842
+ gap: ".5rem",
843
+ fontWeight: "bold"
844
+ },
845
+ children: [
846
+ /* @__PURE__ */ jsx("div", { children: "Cached Matches" }),
847
+ /* @__PURE__ */ jsx(
848
+ "div",
849
+ {
850
+ style: {
851
+ opacity: 0.3,
852
+ fontSize: "0.7rem",
853
+ fontWeight: "normal"
854
+ },
855
+ children: "age / staleTime / gcTime"
856
+ }
857
+ )
858
+ ]
859
+ }
860
+ ),
861
+ /* @__PURE__ */ jsx("div", { children: routerState.cachedMatches.map((match) => {
862
+ return /* @__PURE__ */ jsxs(
863
+ "div",
864
+ {
865
+ role: "button",
866
+ "aria-label": `Open match details for ${match.id}`,
867
+ onClick: () => setActiveId(activeId === match.id ? "" : match.id),
868
+ style: {
869
+ display: "flex",
870
+ borderBottom: `solid 1px ${defaultTheme.grayAlt}`,
871
+ cursor: "pointer",
872
+ alignItems: "center",
873
+ background: match === activeMatch ? "rgba(255,255,255,.1)" : void 0,
874
+ fontSize: "0.7rem"
875
+ },
876
+ children: [
877
+ /* @__PURE__ */ jsx(
878
+ "div",
879
+ {
880
+ style: {
881
+ flex: "0 0 auto",
882
+ width: ".75rem",
883
+ height: ".75rem",
884
+ marginLeft: ".25rem",
885
+ background: getStatusColor(match, defaultTheme),
886
+ alignItems: "center",
887
+ justifyContent: "center",
888
+ fontWeight: "bold",
889
+ borderRadius: "100%",
890
+ transition: "all 1s ease-out"
891
+ }
892
+ }
893
+ ),
894
+ /* @__PURE__ */ jsx(
895
+ Code,
896
+ {
897
+ style: {
898
+ padding: ".5em"
899
+ },
900
+ children: `${match.id}`
901
+ }
902
+ ),
903
+ /* @__PURE__ */ jsx("div", { style: { marginLeft: "auto" }, children: /* @__PURE__ */ jsx(AgeTicker, { match }) })
904
+ ]
905
+ },
906
+ match.id
907
+ );
908
+ }) })
909
+ ]
910
+ }
911
+ ) : null
912
+ ]
913
+ }
914
+ ),
915
+ activeMatch ? /* @__PURE__ */ jsxs(ActivePanel, { children: [
916
+ /* @__PURE__ */ jsx(
917
+ "div",
918
+ {
919
+ style: {
920
+ padding: ".5em",
921
+ background: defaultTheme.backgroundAlt,
922
+ position: "sticky",
923
+ top: 0,
924
+ bottom: 0,
925
+ zIndex: 1
926
+ },
927
+ children: "Match Details"
928
+ }
929
+ ),
930
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
931
+ "table",
932
+ {
933
+ style: {
934
+ fontSize: "0.8rem"
935
+ },
936
+ children: /* @__PURE__ */ jsxs("tbody", { children: [
937
+ /* @__PURE__ */ jsxs("tr", { children: [
938
+ /* @__PURE__ */ jsx("td", { style: { opacity: ".5" }, children: "ID" }),
939
+ /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(
940
+ Code,
941
+ {
942
+ style: {
943
+ lineHeight: "1.8em"
944
+ },
945
+ children: JSON.stringify(activeMatch.id, null, 2)
946
+ }
947
+ ) })
948
+ ] }),
949
+ /* @__PURE__ */ jsxs("tr", { children: [
950
+ /* @__PURE__ */ jsx("td", { style: { opacity: ".5" }, children: "Status" }),
951
+ /* @__PURE__ */ jsxs("td", { children: [
952
+ ((_b = routerState.pendingMatches) == null ? void 0 : _b.find(
953
+ (d) => d.id === activeMatch.id
954
+ )) ? "Pending" : ((_c = routerState.matches) == null ? void 0 : _c.find(
955
+ (d) => d.id === activeMatch.id
956
+ )) ? "Active" : "Cached",
957
+ " ",
958
+ "- ",
959
+ activeMatch.status
960
+ ] })
961
+ ] }),
962
+ /* @__PURE__ */ jsxs("tr", { children: [
963
+ /* @__PURE__ */ jsx("td", { style: { opacity: ".5" }, children: "Last Updated" }),
964
+ /* @__PURE__ */ jsx("td", { children: activeMatch.updatedAt ? new Date(
965
+ activeMatch.updatedAt
966
+ ).toLocaleTimeString() : "N/A" })
967
+ ] })
968
+ ] })
969
+ }
970
+ ) }),
971
+ activeMatch.loaderData ? /* @__PURE__ */ jsxs(Fragment, { children: [
972
+ /* @__PURE__ */ jsx(
973
+ "div",
974
+ {
975
+ style: {
976
+ background: defaultTheme.backgroundAlt,
977
+ padding: ".5em",
978
+ position: "sticky",
979
+ top: 0,
980
+ bottom: 0,
981
+ zIndex: 1
982
+ },
983
+ children: "Loader Data"
984
+ }
985
+ ),
986
+ /* @__PURE__ */ jsx(
987
+ "div",
988
+ {
989
+ style: {
990
+ padding: ".5em"
991
+ },
992
+ children: /* @__PURE__ */ jsx(
993
+ Explorer,
994
+ {
995
+ label: "loaderData",
996
+ value: activeMatch.loaderData,
997
+ defaultExpanded: {}
998
+ }
999
+ )
1000
+ }
1001
+ )
1002
+ ] }) : null,
1003
+ /* @__PURE__ */ jsx(
1004
+ "div",
1005
+ {
1006
+ style: {
1007
+ background: defaultTheme.backgroundAlt,
1008
+ padding: ".5em",
1009
+ position: "sticky",
1010
+ top: 0,
1011
+ bottom: 0,
1012
+ zIndex: 1
1013
+ },
1014
+ children: "Explorer"
1015
+ }
1016
+ ),
1017
+ /* @__PURE__ */ jsx(
1018
+ "div",
1019
+ {
1020
+ style: {
1021
+ padding: ".5em"
1022
+ },
1023
+ children: /* @__PURE__ */ jsx(
1024
+ Explorer,
1025
+ {
1026
+ label: "Match",
1027
+ value: activeMatch,
1028
+ defaultExpanded: {}
1029
+ }
1030
+ )
1031
+ }
1032
+ )
1033
+ ] }) : null,
1034
+ hasSearch ? /* @__PURE__ */ jsxs(
1035
+ "div",
1036
+ {
1037
+ style: {
1038
+ flex: "1 1 500px",
1039
+ minHeight: "40%",
1040
+ maxHeight: "100%",
1041
+ overflow: "auto",
1042
+ borderRight: `1px solid ${defaultTheme.grayAlt}`,
1043
+ display: "flex",
1044
+ flexDirection: "column"
1045
+ },
1046
+ children: [
1047
+ /* @__PURE__ */ jsx(
1048
+ "div",
1049
+ {
1050
+ style: {
1051
+ padding: ".5em",
1052
+ background: defaultTheme.backgroundAlt,
1053
+ position: "sticky",
1054
+ top: 0,
1055
+ bottom: 0,
1056
+ zIndex: 1,
1057
+ fontWeight: "bold"
1058
+ },
1059
+ children: "Search Params"
1060
+ }
1061
+ ),
1062
+ /* @__PURE__ */ jsx(
1063
+ "div",
1064
+ {
1065
+ style: {
1066
+ padding: ".5em"
1067
+ },
1068
+ children: /* @__PURE__ */ jsx(
1069
+ Explorer,
1070
+ {
1071
+ value: routerState.location.search || {},
1072
+ defaultExpanded: Object.keys(
1073
+ routerState.location.search || {}
1074
+ ).reduce((obj, next) => {
1075
+ obj[next] = {};
1076
+ return obj;
1077
+ }, {})
1078
+ }
1079
+ )
1080
+ }
1081
+ )
1082
+ ]
1083
+ }
1084
+ ) : null
1085
+ ] }) });
1086
+ });
1087
+ function AgeTicker({ match }) {
1088
+ const router = useRouter();
1089
+ const rerender = React__default.useReducer(
1090
+ () => ({}),
1091
+ () => ({})
1092
+ )[1];
1093
+ React__default.useEffect(() => {
1094
+ const interval = setInterval(() => {
1095
+ rerender();
1096
+ }, 1e3);
1097
+ return () => {
1098
+ clearInterval(interval);
1099
+ };
1100
+ }, []);
1101
+ if (!match) {
1102
+ return null;
1103
+ }
1104
+ const route = router.looseRoutesById[match == null ? void 0 : match.routeId];
1105
+ if (!route.options.loader) {
1106
+ return null;
1107
+ }
1108
+ const age = Date.now() - (match == null ? void 0 : match.updatedAt);
1109
+ const staleTime = route.options.staleTime ?? router.options.defaultStaleTime ?? 0;
1110
+ const gcTime = route.options.gcTime ?? router.options.defaultGcTime ?? 30 * 60 * 1e3;
1111
+ return /* @__PURE__ */ jsxs(
1112
+ "div",
1113
+ {
1114
+ style: {
1115
+ display: "inline-flex",
1116
+ alignItems: "center",
1117
+ gap: ".25rem",
1118
+ color: age > staleTime ? defaultTheme.warning : void 0
1119
+ },
1120
+ children: [
1121
+ /* @__PURE__ */ jsx("div", { style: {}, children: formatTime(age) }),
1122
+ /* @__PURE__ */ jsx("div", { children: "/" }),
1123
+ /* @__PURE__ */ jsx("div", { children: formatTime(staleTime) }),
1124
+ /* @__PURE__ */ jsx("div", { children: "/" }),
1125
+ /* @__PURE__ */ jsx("div", { children: formatTime(gcTime) })
1126
+ ]
1127
+ }
1128
+ );
1129
+ }
1130
+ function formatTime(ms) {
1131
+ const units = ["s", "min", "h", "d"];
1132
+ const values = [ms / 1e3, ms / 6e4, ms / 36e5, ms / 864e5];
1133
+ let chosenUnitIndex = 0;
1134
+ for (let i = 1; i < values.length; i++) {
1135
+ if (values[i] < 1)
1136
+ break;
1137
+ chosenUnitIndex = i;
1138
+ }
1139
+ const formatter = new Intl.NumberFormat(navigator.language, {
1140
+ compactDisplay: "short",
1141
+ notation: "compact",
1142
+ maximumFractionDigits: 0
1143
+ });
1144
+ return formatter.format(values[chosenUnitIndex]) + units[chosenUnitIndex];
1145
+ }
1146
+ export {
1147
+ TanStackRouterDevtools,
1148
+ TanStackRouterDevtoolsPanel
1149
+ };
1150
+ //# sourceMappingURL=devtools.js.map