@tanstack/router-devtools 1.111.11 → 1.112.4

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