@tanstack/router-devtools-core 1.132.51 → 1.133.1

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 (29) hide show
  1. package/dist/{BaseTanStackRouterDevtoolsPanel-CaAQWNvS.js → BaseTanStackRouterDevtoolsPanel-Cbvcs84k.js} +263 -148
  2. package/dist/BaseTanStackRouterDevtoolsPanel-Cbvcs84k.js.map +1 -0
  3. package/dist/{BaseTanStackRouterDevtoolsPanel-CbH9Ihs_.cjs → BaseTanStackRouterDevtoolsPanel-CiObEXSM.cjs} +262 -147
  4. package/dist/BaseTanStackRouterDevtoolsPanel-CiObEXSM.cjs.map +1 -0
  5. package/dist/{FloatingTanStackRouterDevtools-0xtXUOcx.cjs → FloatingTanStackRouterDevtools-BMhRQRk5.cjs} +3 -3
  6. package/dist/{FloatingTanStackRouterDevtools-0xtXUOcx.cjs.map → FloatingTanStackRouterDevtools-BMhRQRk5.cjs.map} +1 -1
  7. package/dist/{FloatingTanStackRouterDevtools-DdHNTjWg.js → FloatingTanStackRouterDevtools-KvPiI7YB.js} +3 -3
  8. package/dist/{FloatingTanStackRouterDevtools-DdHNTjWg.js.map → FloatingTanStackRouterDevtools-KvPiI7YB.js.map} +1 -1
  9. package/dist/cjs/TanStackRouterDevtoolsCore.d.cts +4 -5
  10. package/dist/cjs/TanStackRouterDevtoolsPanelCore.d.cts +2 -3
  11. package/dist/cjs/index.cjs +1 -1
  12. package/dist/cjs/useStyles.d.cts +2 -0
  13. package/dist/esm/TanStackRouterDevtoolsCore.d.ts +4 -5
  14. package/dist/esm/TanStackRouterDevtoolsPanelCore.d.ts +2 -3
  15. package/dist/esm/index.js +1 -1
  16. package/dist/esm/useStyles.d.ts +2 -0
  17. package/dist/{index-BiZF0hsR.js → index-Bz4rofgr.js} +3 -3
  18. package/dist/index-Bz4rofgr.js.map +1 -0
  19. package/dist/{index-CHaaetqh.cjs → index-sVJ8jjbP.cjs} +3 -3
  20. package/dist/index-sVJ8jjbP.cjs.map +1 -0
  21. package/package.json +1 -1
  22. package/src/BaseTanStackRouterDevtoolsPanel.tsx +169 -57
  23. package/src/TanStackRouterDevtoolsCore.tsx +4 -6
  24. package/src/TanStackRouterDevtoolsPanelCore.tsx +2 -4
  25. package/src/useStyles.tsx +10 -0
  26. package/dist/BaseTanStackRouterDevtoolsPanel-CaAQWNvS.js.map +0 -1
  27. package/dist/BaseTanStackRouterDevtoolsPanel-CbH9Ihs_.cjs.map +0 -1
  28. package/dist/index-BiZF0hsR.js.map +0 -1
  29. package/dist/index-CHaaetqh.cjs.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 ? (
@@ -4,7 +4,7 @@ import { ShadowDomTargetContext } from './context'
4
4
  import type { AnyRouter } from '@tanstack/router-core'
5
5
  import type { Signal } from 'solid-js'
6
6
 
7
- interface DevtoolsOptions {
7
+ export interface TanStackRouterDevtoolsCoreOptions {
8
8
  /**
9
9
  * Set this true if you want the dev tools to default to being open
10
10
  */
@@ -49,7 +49,7 @@ interface DevtoolsOptions {
49
49
  shadowDOMTarget?: ShadowRoot
50
50
  }
51
51
 
52
- class TanStackRouterDevtoolsCore {
52
+ export class TanStackRouterDevtoolsCore {
53
53
  #router: Signal<AnyRouter>
54
54
  #routerState: Signal<any>
55
55
  #position: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
@@ -65,7 +65,7 @@ class TanStackRouterDevtoolsCore {
65
65
  #Component: any
66
66
  #dispose?: () => void
67
67
 
68
- constructor(config: DevtoolsOptions) {
68
+ constructor(config: TanStackRouterDevtoolsCoreOptions) {
69
69
  this.#router = createSignal(config.router)
70
70
  this.#routerState = createSignal(config.routerState)
71
71
  this.#position = config.position ?? 'bottom-left'
@@ -141,7 +141,7 @@ class TanStackRouterDevtoolsCore {
141
141
  this.#routerState[1](routerState)
142
142
  }
143
143
 
144
- setOptions(options: Partial<DevtoolsOptions>) {
144
+ setOptions(options: Partial<TanStackRouterDevtoolsCoreOptions>) {
145
145
  if (options.position !== undefined) {
146
146
  this.#position = options.position
147
147
  }
@@ -159,5 +159,3 @@ class TanStackRouterDevtoolsCore {
159
159
  }
160
160
  }
161
161
  }
162
-
163
- export { TanStackRouterDevtoolsCore }
@@ -4,7 +4,7 @@ import { DevtoolsOnCloseContext, ShadowDomTargetContext } from './context'
4
4
  import type { JSX } from 'solid-js'
5
5
  import type { AnyRouter } from '@tanstack/router-core'
6
6
 
7
- interface TanStackRouterDevtoolsPanelCoreOptions {
7
+ export interface TanStackRouterDevtoolsPanelCoreOptions {
8
8
  /**
9
9
  * The standard React style object used to style a component with inline styles
10
10
  */
@@ -37,7 +37,7 @@ interface TanStackRouterDevtoolsPanelCoreOptions {
37
37
  shadowDOMTarget?: ShadowRoot
38
38
  }
39
39
 
40
- class TanStackRouterDevtoolsPanelCore {
40
+ export class TanStackRouterDevtoolsPanelCore {
41
41
  #router: any
42
42
  #routerState: any
43
43
  #style: any
@@ -158,5 +158,3 @@ class TanStackRouterDevtoolsPanelCore {
158
158
  }
159
159
  }
160
160
  }
161
-
162
- export { TanStackRouterDevtoolsPanelCore }
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;