@tanstack/router-devtools-core 1.132.50 → 1.133.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 (73) hide show
  1. package/dist/BaseTanStackRouterDevtoolsPanel-Cbvcs84k.js +1932 -0
  2. package/dist/BaseTanStackRouterDevtoolsPanel-Cbvcs84k.js.map +1 -0
  3. package/dist/BaseTanStackRouterDevtoolsPanel-CiObEXSM.cjs +1948 -0
  4. package/dist/BaseTanStackRouterDevtoolsPanel-CiObEXSM.cjs.map +1 -0
  5. package/dist/FloatingTanStackRouterDevtools-BMhRQRk5.cjs +283 -0
  6. package/dist/FloatingTanStackRouterDevtools-BMhRQRk5.cjs.map +1 -0
  7. package/dist/FloatingTanStackRouterDevtools-KvPiI7YB.js +283 -0
  8. package/dist/FloatingTanStackRouterDevtools-KvPiI7YB.js.map +1 -0
  9. package/dist/cjs/index.cjs +3 -4
  10. package/dist/cjs/index.cjs.map +1 -1
  11. package/dist/cjs/useStyles.d.cts +2 -0
  12. package/dist/esm/index.js +3 -4
  13. package/dist/esm/index.js.map +1 -1
  14. package/dist/esm/useStyles.d.ts +2 -0
  15. package/dist/index-Bz4rofgr.js +222 -0
  16. package/dist/index-Bz4rofgr.js.map +1 -0
  17. package/dist/index-sVJ8jjbP.cjs +221 -0
  18. package/dist/index-sVJ8jjbP.cjs.map +1 -0
  19. package/package.json +2 -2
  20. package/src/BaseTanStackRouterDevtoolsPanel.tsx +169 -57
  21. package/src/useStyles.tsx +10 -0
  22. package/dist/cjs/AgeTicker.cjs +0 -47
  23. package/dist/cjs/AgeTicker.cjs.map +0 -1
  24. package/dist/cjs/BaseTanStackRouterDevtoolsPanel.cjs +0 -604
  25. package/dist/cjs/BaseTanStackRouterDevtoolsPanel.cjs.map +0 -1
  26. package/dist/cjs/Explorer.cjs +0 -307
  27. package/dist/cjs/Explorer.cjs.map +0 -1
  28. package/dist/cjs/FloatingTanStackRouterDevtools.cjs +0 -201
  29. package/dist/cjs/FloatingTanStackRouterDevtools.cjs.map +0 -1
  30. package/dist/cjs/NavigateButton.cjs +0 -30
  31. package/dist/cjs/NavigateButton.cjs.map +0 -1
  32. package/dist/cjs/TanStackRouterDevtoolsCore.cjs +0 -100
  33. package/dist/cjs/TanStackRouterDevtoolsCore.cjs.map +0 -1
  34. package/dist/cjs/TanStackRouterDevtoolsPanelCore.cjs +0 -113
  35. package/dist/cjs/TanStackRouterDevtoolsPanelCore.cjs.map +0 -1
  36. package/dist/cjs/context.cjs +0 -20
  37. package/dist/cjs/context.cjs.map +0 -1
  38. package/dist/cjs/logo.cjs +0 -92
  39. package/dist/cjs/logo.cjs.map +0 -1
  40. package/dist/cjs/tokens.cjs +0 -201
  41. package/dist/cjs/tokens.cjs.map +0 -1
  42. package/dist/cjs/useLocalStorage.cjs +0 -42
  43. package/dist/cjs/useLocalStorage.cjs.map +0 -1
  44. package/dist/cjs/useStyles.cjs +0 -607
  45. package/dist/cjs/useStyles.cjs.map +0 -1
  46. package/dist/cjs/utils.cjs +0 -63
  47. package/dist/cjs/utils.cjs.map +0 -1
  48. package/dist/esm/AgeTicker.js +0 -47
  49. package/dist/esm/AgeTicker.js.map +0 -1
  50. package/dist/esm/BaseTanStackRouterDevtoolsPanel.js +0 -604
  51. package/dist/esm/BaseTanStackRouterDevtoolsPanel.js.map +0 -1
  52. package/dist/esm/Explorer.js +0 -290
  53. package/dist/esm/Explorer.js.map +0 -1
  54. package/dist/esm/FloatingTanStackRouterDevtools.js +0 -201
  55. package/dist/esm/FloatingTanStackRouterDevtools.js.map +0 -1
  56. package/dist/esm/NavigateButton.js +0 -30
  57. package/dist/esm/NavigateButton.js.map +0 -1
  58. package/dist/esm/TanStackRouterDevtoolsCore.js +0 -100
  59. package/dist/esm/TanStackRouterDevtoolsCore.js.map +0 -1
  60. package/dist/esm/TanStackRouterDevtoolsPanelCore.js +0 -113
  61. package/dist/esm/TanStackRouterDevtoolsPanelCore.js.map +0 -1
  62. package/dist/esm/context.js +0 -20
  63. package/dist/esm/context.js.map +0 -1
  64. package/dist/esm/logo.js +0 -92
  65. package/dist/esm/logo.js.map +0 -1
  66. package/dist/esm/tokens.js +0 -201
  67. package/dist/esm/tokens.js.map +0 -1
  68. package/dist/esm/useLocalStorage.js +0 -43
  69. package/dist/esm/useLocalStorage.js.map +0 -1
  70. package/dist/esm/useStyles.js +0 -590
  71. package/dist/esm/useStyles.js.map +0 -1
  72. package/dist/esm/utils.js +0 -63
  73. package/dist/esm/utils.js.map +0 -1
@@ -1,7 +1,17 @@
1
1
  import { clsx as cx } from 'clsx'
2
2
  import { default as invariant } from 'tiny-invariant'
3
3
  import { interpolatePath, rootRouteId, trimPath } from '@tanstack/router-core'
4
- import { Show, createMemo, createSignal, onCleanup } from 'solid-js'
4
+ import {
5
+ For,
6
+ Match,
7
+ Show,
8
+ Switch,
9
+ createEffect,
10
+ createMemo,
11
+ createSignal,
12
+ onCleanup,
13
+ untrack,
14
+ } from 'solid-js'
5
15
  import { useDevtoolsOnClose } from './context'
6
16
  import { useStyles } from './useStyles'
7
17
  import useLocalStorage from './useLocalStorage'
@@ -14,6 +24,7 @@ import { NavigateButton } from './NavigateButton'
14
24
  import type {
15
25
  AnyContext,
16
26
  AnyRoute,
27
+ AnyRouteMatch,
17
28
  AnyRouter,
18
29
  FileRouteTypes,
19
30
  MakeRouteMatchUnion,
@@ -54,6 +65,8 @@ export interface BaseDevtoolsPanelOptions {
54
65
  shadowDOMTarget?: ShadowRoot
55
66
  }
56
67
 
68
+ const HISTORY_LIMIT = 15
69
+
57
70
  function Logo(props: any) {
58
71
  const { className, ...rest } = props
59
72
  const styles = useStyles()
@@ -257,16 +270,45 @@ export const BaseTanStackRouterDevtoolsPanel =
257
270
 
258
271
  // useStore(router.__store)
259
272
 
260
- const [showMatches, setShowMatches] = useLocalStorage(
261
- 'tanstackRouterDevtoolsShowMatches',
262
- true,
263
- )
273
+ const [currentTab, setCurrentTab] = useLocalStorage<
274
+ 'routes' | 'matches' | 'history'
275
+ >('tanstackRouterDevtoolsActiveTab', 'routes')
264
276
 
265
277
  const [activeId, setActiveId] = useLocalStorage(
266
278
  'tanstackRouterDevtoolsActiveRouteId',
267
279
  '',
268
280
  )
269
281
 
282
+ const [history, setHistory] = createSignal<Array<AnyRouteMatch>>([])
283
+ const [hasHistoryOverflowed, setHasHistoryOverflowed] = createSignal(false)
284
+
285
+ createEffect(() => {
286
+ const matches = routerState().matches
287
+ const currentMatch = matches[matches.length - 1]
288
+ if (!currentMatch) {
289
+ return
290
+ }
291
+ // Read history WITHOUT tracking it to avoid infinite loops
292
+ const historyUntracked = untrack(() => history())
293
+ const lastMatch = historyUntracked[0]
294
+ const sameLocation =
295
+ lastMatch &&
296
+ lastMatch.pathname === currentMatch.pathname &&
297
+ JSON.stringify(lastMatch.search ?? {}) ===
298
+ JSON.stringify(currentMatch.search ?? {})
299
+ if (!lastMatch || !sameLocation) {
300
+ if (historyUntracked.length >= HISTORY_LIMIT) {
301
+ setHasHistoryOverflowed(true)
302
+ }
303
+ setHistory((prev) => {
304
+ const newHistory = [currentMatch, ...prev]
305
+ // truncate to ensure we don't overflow too much the ui
306
+ newHistory.splice(HISTORY_LIMIT)
307
+ return newHistory
308
+ })
309
+ }
310
+ })
311
+
270
312
  const activeMatch = createMemo(() => {
271
313
  const matches = [
272
314
  ...(routerState().pendingMatches ?? []),
@@ -421,11 +463,14 @@ export const BaseTanStackRouterDevtoolsPanel =
421
463
  <button
422
464
  type="button"
423
465
  onClick={() => {
424
- setShowMatches(false)
466
+ setCurrentTab('routes')
425
467
  }}
426
- disabled={!showMatches()}
468
+ disabled={currentTab() === 'routes'}
427
469
  class={cx(
428
- styles().routeMatchesToggleBtn(!showMatches(), true),
470
+ styles().routeMatchesToggleBtn(
471
+ currentTab() === 'routes',
472
+ true,
473
+ ),
429
474
  )}
430
475
  >
431
476
  Routes
@@ -433,70 +478,137 @@ export const BaseTanStackRouterDevtoolsPanel =
433
478
  <button
434
479
  type="button"
435
480
  onClick={() => {
436
- setShowMatches(true)
481
+ setCurrentTab('matches')
437
482
  }}
438
- disabled={showMatches()}
483
+ disabled={currentTab() === 'matches'}
439
484
  class={cx(
440
- styles().routeMatchesToggleBtn(!!showMatches(), false),
485
+ styles().routeMatchesToggleBtn(
486
+ currentTab() === 'matches',
487
+ true,
488
+ ),
441
489
  )}
442
490
  >
443
491
  Matches
444
492
  </button>
493
+ <button
494
+ type="button"
495
+ onClick={() => {
496
+ setCurrentTab('history')
497
+ }}
498
+ disabled={currentTab() === 'history'}
499
+ class={cx(
500
+ styles().routeMatchesToggleBtn(
501
+ currentTab() === 'history',
502
+ false,
503
+ ),
504
+ )}
505
+ >
506
+ History
507
+ </button>
445
508
  </div>
446
509
  <div class={styles().detailsHeaderInfo}>
447
510
  <div>age / staleTime / gcTime</div>
448
511
  </div>
449
512
  </div>
450
513
  <div class={cx(styles().routesContainer)}>
451
- {!showMatches() ? (
452
- <RouteComp
453
- routerState={routerState}
454
- router={router}
455
- route={router().routeTree}
456
- isRoot
457
- activeId={activeId}
458
- setActiveId={setActiveId}
459
- />
460
- ) : (
461
- <div>
462
- {(routerState().pendingMatches?.length
463
- ? routerState().pendingMatches
464
- : routerState().matches
465
- )?.map((match: any, _i: any) => {
466
- return (
467
- <div
468
- role="button"
469
- aria-label={`Open match details for ${match.id}`}
470
- onClick={() =>
471
- setActiveId(activeId() === match.id ? '' : match.id)
472
- }
473
- class={cx(styles().matchRow(match === activeMatch()))}
474
- >
514
+ <Switch>
515
+ <Match when={currentTab() === 'routes'}>
516
+ <RouteComp
517
+ routerState={routerState}
518
+ router={router}
519
+ route={router().routeTree}
520
+ isRoot
521
+ activeId={activeId}
522
+ setActiveId={setActiveId}
523
+ />
524
+ </Match>
525
+ <Match when={currentTab() === 'matches'}>
526
+ <div>
527
+ {(routerState().pendingMatches?.length
528
+ ? routerState().pendingMatches
529
+ : routerState().matches
530
+ )?.map((match: any, _i: any) => {
531
+ return (
475
532
  <div
476
- class={cx(
477
- styles().matchIndicator(getStatusColor(match)),
478
- )}
479
- />
480
- <NavigateLink
481
- left={
482
- <NavigateButton
483
- to={match.pathname}
484
- params={match.params}
485
- search={match.search}
486
- router={router}
487
- />
533
+ role="button"
534
+ aria-label={`Open match details for ${match.id}`}
535
+ onClick={() =>
536
+ setActiveId(activeId() === match.id ? '' : match.id)
488
537
  }
489
- right={<AgeTicker match={match} router={router} />}
538
+ class={cx(styles().matchRow(match === activeMatch()))}
490
539
  >
491
- <code class={styles().matchID}>
492
- {`${match.routeId === rootRouteId ? rootRouteId : match.pathname}`}
493
- </code>
494
- </NavigateLink>
495
- </div>
496
- )
497
- })}
498
- </div>
499
- )}
540
+ <div
541
+ class={cx(
542
+ styles().matchIndicator(getStatusColor(match)),
543
+ )}
544
+ />
545
+ <NavigateLink
546
+ left={
547
+ <NavigateButton
548
+ to={match.pathname}
549
+ params={match.params}
550
+ search={match.search}
551
+ router={router}
552
+ />
553
+ }
554
+ right={<AgeTicker match={match} router={router} />}
555
+ >
556
+ <code class={styles().matchID}>
557
+ {`${match.routeId === rootRouteId ? rootRouteId : match.pathname}`}
558
+ </code>
559
+ </NavigateLink>
560
+ </div>
561
+ )
562
+ })}
563
+ </div>
564
+ </Match>
565
+ <Match when={currentTab() === 'history'}>
566
+ <div>
567
+ <ul>
568
+ <For each={history()}>
569
+ {(match, index) => (
570
+ <li
571
+ class={cx(
572
+ styles().matchRow(match === activeMatch()),
573
+ )}
574
+ >
575
+ <div
576
+ class={cx(
577
+ styles().matchIndicator(
578
+ index() === 0 ? 'green' : 'gray',
579
+ ),
580
+ )}
581
+ />
582
+ <NavigateLink
583
+ left={
584
+ <NavigateButton
585
+ to={match.pathname}
586
+ params={match.params}
587
+ search={match.search}
588
+ router={router}
589
+ />
590
+ }
591
+ right={
592
+ <AgeTicker match={match} router={router} />
593
+ }
594
+ >
595
+ <code class={styles().matchID}>
596
+ {`${match.routeId === rootRouteId ? rootRouteId : match.pathname}`}
597
+ </code>
598
+ </NavigateLink>
599
+ </li>
600
+ )}
601
+ </For>
602
+ {hasHistoryOverflowed() ? (
603
+ <li class={styles().historyOverflowContainer}>
604
+ This panel displays the most recent {HISTORY_LIMIT}{' '}
605
+ navigations.
606
+ </li>
607
+ ) : null}
608
+ </ul>
609
+ </div>
610
+ </Match>
611
+ </Switch>
500
612
  </div>
501
613
  </div>
502
614
  {routerState().cachedMatches.length ? (
package/src/useStyles.tsx CHANGED
@@ -404,6 +404,16 @@ const stylesFactory = (shadowDOMTarget?: ShadowRoot) => {
404
404
  overflow-y: auto;
405
405
  max-height: 50%;
406
406
  `,
407
+ historyContainer: css`
408
+ display: flex;
409
+ flex: 1 1 auto;
410
+ overflow-y: auto;
411
+ max-height: 50%;
412
+ `,
413
+ historyOverflowContainer: css`
414
+ padding: ${size[1]} ${size[2]};
415
+ font-size: ${tokens.font.size.xs};
416
+ `,
407
417
  maskedBadgeContainer: css`
408
418
  flex: 1;
409
419
  justify-content: flex-end;
@@ -1,47 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const web = require("solid-js/web");
4
- const clsx = require("clsx");
5
- const useStyles = require("./useStyles.cjs");
6
- var _tmpl$ = /* @__PURE__ */ web.template(`<div><div></div><div>/</div><div></div><div>/</div><div>`);
7
- function formatTime(ms) {
8
- const units = ["s", "min", "h", "d"];
9
- const values = [ms / 1e3, ms / 6e4, ms / 36e5, ms / 864e5];
10
- let chosenUnitIndex = 0;
11
- for (let i = 1; i < values.length; i++) {
12
- if (values[i] < 1) break;
13
- chosenUnitIndex = i;
14
- }
15
- const formatter = new Intl.NumberFormat(navigator.language, {
16
- compactDisplay: "short",
17
- notation: "compact",
18
- maximumFractionDigits: 0
19
- });
20
- return formatter.format(values[chosenUnitIndex]) + units[chosenUnitIndex];
21
- }
22
- function AgeTicker({
23
- match,
24
- router
25
- }) {
26
- const styles = useStyles.useStyles();
27
- if (!match) {
28
- return null;
29
- }
30
- const route = router().looseRoutesById[match.routeId];
31
- if (!route.options.loader) {
32
- return null;
33
- }
34
- const age = Date.now() - match.updatedAt;
35
- const staleTime = route.options.staleTime ?? router().options.defaultStaleTime ?? 0;
36
- const gcTime = route.options.gcTime ?? router().options.defaultGcTime ?? 30 * 60 * 1e3;
37
- return (() => {
38
- var _el$ = _tmpl$(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling, _el$4 = _el$3.nextSibling, _el$5 = _el$4.nextSibling, _el$6 = _el$5.nextSibling;
39
- web.insert(_el$2, () => formatTime(age));
40
- web.insert(_el$4, () => formatTime(staleTime));
41
- web.insert(_el$6, () => formatTime(gcTime));
42
- web.effect(() => web.className(_el$, clsx.clsx(styles().ageTicker(age > staleTime))));
43
- return _el$;
44
- })();
45
- }
46
- exports.AgeTicker = AgeTicker;
47
- //# sourceMappingURL=AgeTicker.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AgeTicker.cjs","sources":["../../src/AgeTicker.tsx"],"sourcesContent":["import { clsx as cx } from 'clsx'\nimport { useStyles } from './useStyles'\nimport type { AnyRouteMatch, AnyRouter } from '@tanstack/router-core'\nimport type { Accessor } from 'solid-js'\n\nfunction formatTime(ms: number) {\n const units = ['s', 'min', 'h', 'd']\n const values = [ms / 1000, ms / 60000, ms / 3600000, ms / 86400000]\n\n let chosenUnitIndex = 0\n for (let i = 1; i < values.length; i++) {\n if (values[i]! < 1) break\n chosenUnitIndex = i\n }\n\n const formatter = new Intl.NumberFormat(navigator.language, {\n compactDisplay: 'short',\n notation: 'compact',\n maximumFractionDigits: 0,\n })\n\n return formatter.format(values[chosenUnitIndex]!) + units[chosenUnitIndex]\n}\n\nexport function AgeTicker({\n match,\n router,\n}: {\n match?: AnyRouteMatch\n router: Accessor<AnyRouter>\n}) {\n const styles = useStyles()\n\n if (!match) {\n return null\n }\n\n const route = router().looseRoutesById[match.routeId]!\n\n if (!route.options.loader) {\n return null\n }\n\n const age = Date.now() - match.updatedAt\n const staleTime =\n route.options.staleTime ?? router().options.defaultStaleTime ?? 0\n const gcTime =\n route.options.gcTime ?? router().options.defaultGcTime ?? 30 * 60 * 1000\n\n return (\n <div class={cx(styles().ageTicker(age > staleTime))}>\n <div>{formatTime(age)}</div>\n <div>/</div>\n <div>{formatTime(staleTime)}</div>\n <div>/</div>\n <div>{formatTime(gcTime)}</div>\n </div>\n )\n}\n"],"names":["formatTime","ms","units","values","chosenUnitIndex","i","length","formatter","Intl","NumberFormat","navigator","language","compactDisplay","notation","maximumFractionDigits","format","AgeTicker","match","router","styles","useStyles","route","looseRoutesById","routeId","options","loader","age","Date","now","updatedAt","staleTime","defaultStaleTime","gcTime","defaultGcTime","_el$","_tmpl$","_el$2","firstChild","_el$3","nextSibling","_el$4","_el$5","_el$6","_$insert","_$effect","_$className","cx","ageTicker"],"mappings":";;;;;;AAKA,SAASA,WAAWC,IAAY;AAC9B,QAAMC,QAAQ,CAAC,KAAK,OAAO,KAAK,GAAG;AACnC,QAAMC,SAAS,CAACF,KAAK,KAAMA,KAAK,KAAOA,KAAK,MAASA,KAAK,KAAQ;AAElE,MAAIG,kBAAkB;AACtB,WAASC,IAAI,GAAGA,IAAIF,OAAOG,QAAQD,KAAK;AACtC,QAAIF,OAAOE,CAAC,IAAK,EAAG;AACpBD,sBAAkBC;AAAAA,EACpB;AAEA,QAAME,YAAY,IAAIC,KAAKC,aAAaC,UAAUC,UAAU;AAAA,IAC1DC,gBAAgB;AAAA,IAChBC,UAAU;AAAA,IACVC,uBAAuB;AAAA,EAAA,CACxB;AAED,SAAOP,UAAUQ,OAAOZ,OAAOC,eAAe,CAAE,IAAIF,MAAME,eAAe;AAC3E;AAEO,SAASY,UAAU;AAAA,EACxBC;AAAAA,EACAC;AAIF,GAAG;AACD,QAAMC,SAASC,UAAAA,UAAAA;AAEf,MAAI,CAACH,OAAO;AACV,WAAO;AAAA,EACT;AAEA,QAAMI,QAAQH,OAAAA,EAASI,gBAAgBL,MAAMM,OAAO;AAEpD,MAAI,CAACF,MAAMG,QAAQC,QAAQ;AACzB,WAAO;AAAA,EACT;AAEA,QAAMC,MAAMC,KAAKC,IAAAA,IAAQX,MAAMY;AAC/B,QAAMC,YACJT,MAAMG,QAAQM,aAAaZ,SAASM,QAAQO,oBAAoB;AAClE,QAAMC,SACJX,MAAMG,QAAQQ,UAAUd,SAASM,QAAQS,iBAAiB,KAAK,KAAK;AAEtE,UAAA,MAAA;AAAA,QAAAC,OAAAC,UAAAC,QAAAF,KAAAG,YAAAC,QAAAF,MAAAG,aAAAC,QAAAF,MAAAC,aAAAE,QAAAD,MAAAD,aAAAG,QAAAD,MAAAF;AAAAI,QAAAA,OAAAP,OAAA,MAEUpC,WAAW0B,GAAG,CAAC;AAAAiB,QAAAA,OAAAH,OAAA,MAEfxC,WAAW8B,SAAS,CAAC;AAAAa,QAAAA,OAAAD,OAAA,MAErB1C,WAAWgC,MAAM,CAAC;AAAAY,QAAAA,aAAAC,IAAAA,UAAAX,MALdY,UAAG3B,SAAS4B,UAAUrB,MAAMI,SAAS,CAAC,CAAC,CAAA;AAAA,WAAAI;AAAAA,EAAA,GAAA;AAQvD;;"}