@tanstack/router-devtools 1.17.0 → 1.17.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.
package/src/devtools.tsx CHANGED
@@ -102,9 +102,9 @@ const isServer = typeof window === 'undefined'
102
102
  function Logo(props: React.HTMLAttributes<HTMLButtonElement>) {
103
103
  const { className, ...rest } = props
104
104
  return (
105
- <button {...rest} className={cx(styles.logo, className)}>
106
- <div className={styles.tanstackLogo}>TANSTACK</div>
107
- <div className={styles.routerLogo}>React Router v1</div>
105
+ <button {...rest} className={cx(getStyles().logo, className)}>
106
+ <div className={getStyles().tanstackLogo}>TANSTACK</div>
107
+ <div className={getStyles().routerLogo}>React Router v1</div>
108
108
  </button>
109
109
  )
110
110
  }
@@ -135,7 +135,7 @@ export function TanStackRouterDevtools({
135
135
  containerElement: Container = 'footer',
136
136
  router,
137
137
  }: DevtoolsOptions): React.ReactElement | null {
138
- const rootRef = React.useRef<HTMLDivElement>(null)
138
+ const [rootEl, setRootEl] = React.useState<HTMLDivElement>(null!)
139
139
  const panelRef = React.useRef<HTMLDivElement>(null)
140
140
  const [isOpen, setIsOpen] = useLocalStorage(
141
141
  'tanstackRouterDevtoolsOpen',
@@ -191,14 +191,14 @@ export function TanStackRouterDevtools({
191
191
  setIsResolvedOpen(isOpen ?? false)
192
192
  }, [isOpen, isResolvedOpen, setIsResolvedOpen])
193
193
 
194
- React[isServer ? 'useEffect' : 'useLayoutEffect'](() => {
194
+ React.useEffect(() => {
195
195
  if (isResolvedOpen) {
196
- const previousValue = rootRef.current?.parentElement?.style.paddingBottom
196
+ const previousValue = rootEl?.parentElement?.style.paddingBottom
197
197
 
198
198
  const run = () => {
199
199
  const containerHeight = panelRef.current?.getBoundingClientRect().height
200
- if (rootRef.current?.parentElement) {
201
- rootRef.current.parentElement.style.paddingBottom = `${containerHeight}px`
200
+ if (rootEl?.parentElement) {
201
+ rootEl.parentElement.style.paddingBottom = `${containerHeight}px`
202
202
  }
203
203
  }
204
204
 
@@ -209,11 +209,8 @@ export function TanStackRouterDevtools({
209
209
 
210
210
  return () => {
211
211
  window.removeEventListener('resize', run)
212
- if (
213
- rootRef.current?.parentElement &&
214
- typeof previousValue === 'string'
215
- ) {
216
- rootRef.current.parentElement.style.paddingBottom = previousValue
212
+ if (rootEl?.parentElement && typeof previousValue === 'string') {
213
+ rootEl.parentElement.style.paddingBottom = previousValue
217
214
  }
218
215
  }
219
216
  }
@@ -221,13 +218,13 @@ export function TanStackRouterDevtools({
221
218
  return
222
219
  }, [isResolvedOpen])
223
220
 
224
- React[isServer ? 'useEffect' : 'useLayoutEffect'](() => {
225
- if (rootRef.current) {
226
- const el = rootRef.current
221
+ React.useEffect(() => {
222
+ if (rootEl) {
223
+ const el = rootEl
227
224
  const fontSize = getComputedStyle(el).fontSize
228
225
  el.style.setProperty('--tsrd-font-size', fontSize)
229
226
  }
230
- }, [rootRef.current])
227
+ }, [rootEl])
231
228
 
232
229
  const { style: panelStyle = {}, ...otherPanelProps } = panelProps
233
230
 
@@ -249,7 +246,7 @@ export function TanStackRouterDevtools({
249
246
  const resolvedHeight = devtoolsHeight ?? 500
250
247
 
251
248
  return (
252
- <Container ref={rootRef} className="TanStackRouterDevtools">
249
+ <Container ref={setRootEl} className="TanStackRouterDevtools">
253
250
  <DevtoolsOnCloseContext.Provider
254
251
  value={{
255
252
  onCloseClick: onCloseClick ?? (() => {}),
@@ -260,10 +257,10 @@ export function TanStackRouterDevtools({
260
257
  {...otherPanelProps}
261
258
  router={router}
262
259
  className={cx(
263
- styles.devtoolsPanelContainer,
264
- styles.devtoolsPanelContainerVisibility(!!isOpen),
265
- styles.devtoolsPanelContainerResizing(isResizing),
266
- styles.devtoolsPanelContainerAnimation(
260
+ getStyles().devtoolsPanelContainer,
261
+ getStyles().devtoolsPanelContainerVisibility(!!isOpen),
262
+ getStyles().devtoolsPanelContainerResizing(isResizing),
263
+ getStyles().devtoolsPanelContainerAnimation(
267
264
  isResolvedOpen,
268
265
  resolvedHeight + 16,
269
266
  ),
@@ -287,21 +284,21 @@ export function TanStackRouterDevtools({
287
284
  onToggleClick && onToggleClick(e)
288
285
  }}
289
286
  className={cx(
290
- styles.mainCloseBtn,
291
- styles.mainCloseBtnPosition(position),
292
- styles.mainCloseBtnAnimation(!isButtonClosed),
287
+ getStyles().mainCloseBtn,
288
+ getStyles().mainCloseBtnPosition(position),
289
+ getStyles().mainCloseBtnAnimation(!isButtonClosed),
293
290
  )}
294
291
  >
295
- <div className={styles.mainCloseBtnIconContainer}>
296
- <div className={styles.mainCloseBtnIconOuter}>
292
+ <div className={getStyles().mainCloseBtnIconContainer}>
293
+ <div className={getStyles().mainCloseBtnIconOuter}>
297
294
  <TanStackLogo />
298
295
  </div>
299
- <div className={styles.mainCloseBtnIconInner}>
296
+ <div className={getStyles().mainCloseBtnIconInner}>
300
297
  <TanStackLogo />
301
298
  </div>
302
299
  </div>
303
- <div className={styles.mainCloseBtnDivider}>-</div>
304
- <div className={styles.routerLogoCloseButton}>React Router</div>
300
+ <div className={getStyles().mainCloseBtnDivider}>-</div>
301
+ <div className={getStyles().routerLogoCloseButton}>React Router</div>
305
302
  </button>
306
303
  </Container>
307
304
  )
@@ -355,26 +352,26 @@ function RouteComp({
355
352
  }
356
353
  }}
357
354
  className={cx(
358
- styles.routesRowContainer(route.id === activeId, !!match),
355
+ getStyles().routesRowContainer(route.id === activeId, !!match),
359
356
  )}
360
357
  >
361
358
  <div
362
359
  className={cx(
363
- styles.matchIndicator(getRouteStatusColor(matches, route)),
360
+ getStyles().matchIndicator(getRouteStatusColor(matches, route)),
364
361
  )}
365
362
  />
366
- <div className={cx(styles.routesRow(!!match))}>
363
+ <div className={cx(getStyles().routesRow(!!match))}>
367
364
  <div>
368
- <code className={styles.code}>
365
+ <code className={getStyles().code}>
369
366
  {isRoot ? '__root__' : route.path || trimPath(route.id)}{' '}
370
367
  </code>
371
- <code className={styles.routeParamInfo}>{param}</code>
368
+ <code className={getStyles().routeParamInfo}>{param}</code>
372
369
  </div>
373
370
  <AgeTicker match={match} />
374
371
  </div>
375
372
  </div>
376
373
  {(route.children as Route[])?.length ? (
377
- <div className={styles.nestedRouteRow(!!isRoot)}>
374
+ <div className={getStyles().nestedRouteRow(!!isRoot)}>
378
375
  {[...(route.children as Route[])]
379
376
  .sort((a, b) => {
380
377
  return a.rank - b.rank
@@ -453,17 +450,20 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
453
450
  <div
454
451
  ref={ref}
455
452
  className={cx(
456
- styles.devtoolsPanel,
453
+ getStyles().devtoolsPanel,
457
454
  'TanStackRouterDevtoolsPanel',
458
455
  className,
459
456
  )}
460
457
  {...otherPanelProps}
461
458
  >
462
459
  {handleDragStart ? (
463
- <div className={styles.dragHandle} onMouseDown={handleDragStart}></div>
460
+ <div
461
+ className={getStyles().dragHandle}
462
+ onMouseDown={handleDragStart}
463
+ ></div>
464
464
  ) : null}
465
465
  <button
466
- className={styles.panelCloseBtn}
466
+ className={getStyles().panelCloseBtn}
467
467
  onClick={(e) => {
468
468
  setIsOpen(false)
469
469
  onCloseClick(e)
@@ -475,7 +475,7 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
475
475
  height="6"
476
476
  fill="none"
477
477
  viewBox="0 0 10 6"
478
- className={styles.panelCloseBtnIcon}
478
+ className={getStyles().panelCloseBtnIcon}
479
479
  >
480
480
  <path
481
481
  stroke="currentColor"
@@ -486,8 +486,8 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
486
486
  ></path>
487
487
  </svg>
488
488
  </button>
489
- <div className={styles.firstContainer}>
490
- <div className={styles.row}>
489
+ <div className={getStyles().firstContainer}>
490
+ <div className={getStyles().row}>
491
491
  <Logo
492
492
  aria-hidden
493
493
  onClick={(e) => {
@@ -496,8 +496,8 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
496
496
  }}
497
497
  />
498
498
  </div>
499
- <div className={styles.routerExplorerContainer}>
500
- <div className={styles.routerExplorer}>
499
+ <div className={getStyles().routerExplorerContainer}>
500
+ <div className={getStyles().routerExplorer}>
501
501
  <Explorer
502
502
  label="Router"
503
503
  value={Object.fromEntries(
@@ -544,33 +544,35 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
544
544
  </div>
545
545
  </div>
546
546
  </div>
547
- <div className={styles.secondContainer}>
548
- <div className={styles.matchesContainer}>
549
- <div className={styles.detailsHeader}>
547
+ <div className={getStyles().secondContainer}>
548
+ <div className={getStyles().matchesContainer}>
549
+ <div className={getStyles().detailsHeader}>
550
550
  <span>Pathname</span>
551
551
  {routerState.location.maskedLocation ? (
552
- <div className={styles.maskedBadgeContainer}>
553
- <span className={styles.maskedBadge}>masked</span>
552
+ <div className={getStyles().maskedBadgeContainer}>
553
+ <span className={getStyles().maskedBadge}>masked</span>
554
554
  </div>
555
555
  ) : null}
556
556
  </div>
557
- <div className={styles.detailsContent}>
557
+ <div className={getStyles().detailsContent}>
558
558
  <code>{routerState.location.pathname}</code>
559
559
  {routerState.location.maskedLocation ? (
560
- <code className={styles.maskedLocation}>
560
+ <code className={getStyles().maskedLocation}>
561
561
  {routerState.location.maskedLocation.pathname}
562
562
  </code>
563
563
  ) : null}
564
564
  </div>
565
- <div className={styles.detailsHeader}>
566
- <div className={styles.routeMatchesToggle}>
565
+ <div className={getStyles().detailsHeader}>
566
+ <div className={getStyles().routeMatchesToggle}>
567
567
  <button
568
568
  type="button"
569
569
  onClick={() => {
570
570
  setShowMatches(false)
571
571
  }}
572
572
  disabled={!showMatches}
573
- className={cx(styles.routeMatchesToggleBtn(!showMatches, true))}
573
+ className={cx(
574
+ getStyles().routeMatchesToggleBtn(!showMatches, true),
575
+ )}
574
576
  >
575
577
  Routes
576
578
  </button>
@@ -581,13 +583,13 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
581
583
  }}
582
584
  disabled={showMatches}
583
585
  className={cx(
584
- styles.routeMatchesToggleBtn(!!showMatches, false),
586
+ getStyles().routeMatchesToggleBtn(!!showMatches, false),
585
587
  )}
586
588
  >
587
589
  Matches
588
590
  </button>
589
591
  </div>
590
- <div className={styles.detailsHeaderInfo}>
592
+ <div className={getStyles().detailsHeaderInfo}>
591
593
  <div>age / staleTime / gcTime</div>
592
594
  </div>
593
595
  </div>
@@ -612,16 +614,16 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
612
614
  onClick={() =>
613
615
  setActiveId(activeId === match.id ? '' : match.id)
614
616
  }
615
- className={cx(styles.matchRow(match === activeMatch))}
617
+ className={cx(getStyles().matchRow(match === activeMatch))}
616
618
  >
617
619
  <div
618
620
  className={cx(
619
- styles.matchIndicator(getStatusColor(match)),
621
+ getStyles().matchIndicator(getStatusColor(match)),
620
622
  )}
621
623
  />
622
624
 
623
625
  <code
624
- className={styles.matchID}
626
+ className={getStyles().matchID}
625
627
  >{`${match.routeId === '__root__' ? '__root__' : match.pathname}`}</code>
626
628
  <AgeTicker match={match} />
627
629
  </div>
@@ -631,10 +633,10 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
631
633
  )}
632
634
  </div>
633
635
  {routerState.cachedMatches?.length ? (
634
- <div className={styles.cachedMatchesContainer}>
635
- <div className={styles.detailsHeader}>
636
+ <div className={getStyles().cachedMatchesContainer}>
637
+ <div className={getStyles().detailsHeader}>
636
638
  <div>Cached Matches</div>
637
- <div className={styles.detailsHeaderInfo}>
639
+ <div className={getStyles().detailsHeaderInfo}>
638
640
  age / staleTime / gcTime
639
641
  </div>
640
642
  </div>
@@ -648,15 +650,15 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
648
650
  onClick={() =>
649
651
  setActiveId(activeId === match.id ? '' : match.id)
650
652
  }
651
- className={cx(styles.matchRow(match === activeMatch))}
653
+ className={cx(getStyles().matchRow(match === activeMatch))}
652
654
  >
653
655
  <div
654
656
  className={cx(
655
- styles.matchIndicator(getStatusColor(match)),
657
+ getStyles().matchIndicator(getStatusColor(match)),
656
658
  )}
657
659
  />
658
660
 
659
- <code className={styles.matchID}>{`${match.id}`}</code>
661
+ <code className={getStyles().matchID}>{`${match.id}`}</code>
660
662
 
661
663
  <AgeTicker match={match} />
662
664
  </div>
@@ -667,12 +669,12 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
667
669
  ) : null}
668
670
  </div>
669
671
  {activeMatch ? (
670
- <div className={styles.thirdContainer}>
671
- <div className={styles.detailsHeader}>Match Details</div>
672
+ <div className={getStyles().thirdContainer}>
673
+ <div className={getStyles().detailsHeader}>Match Details</div>
672
674
  <div>
673
- <div className={styles.matchDetails}>
675
+ <div className={getStyles().matchDetails}>
674
676
  <div
675
- className={styles.matchStatus(
677
+ className={getStyles().matchStatus(
676
678
  activeMatch.status,
677
679
  activeMatch.isFetching,
678
680
  )}
@@ -683,15 +685,15 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
683
685
  : activeMatch.status}
684
686
  </div>
685
687
  </div>
686
- <div className={styles.matchDetailsInfoLabel}>
688
+ <div className={getStyles().matchDetailsInfoLabel}>
687
689
  <div>ID:</div>
688
- <div className={styles.matchDetailsInfo}>
690
+ <div className={getStyles().matchDetailsInfo}>
689
691
  <code>{activeMatch.id}</code>
690
692
  </div>
691
693
  </div>
692
- <div className={styles.matchDetailsInfoLabel}>
694
+ <div className={getStyles().matchDetailsInfoLabel}>
693
695
  <div>State:</div>
694
- <div className={styles.matchDetailsInfo}>
696
+ <div className={getStyles().matchDetailsInfo}>
695
697
  {routerState.pendingMatches?.find(
696
698
  (d) => d.id === activeMatch.id,
697
699
  )
@@ -701,9 +703,9 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
701
703
  : 'Cached'}
702
704
  </div>
703
705
  </div>
704
- <div className={styles.matchDetailsInfoLabel}>
706
+ <div className={getStyles().matchDetailsInfoLabel}>
705
707
  <div>Last Updated:</div>
706
- <div className={styles.matchDetailsInfo}>
708
+ <div className={getStyles().matchDetailsInfo}>
707
709
  {activeMatch.updatedAt
708
710
  ? new Date(
709
711
  activeMatch.updatedAt as number,
@@ -715,8 +717,8 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
715
717
  </div>
716
718
  {activeMatch.loaderData ? (
717
719
  <>
718
- <div className={styles.detailsHeader}>Loader Data</div>
719
- <div className={styles.detailsContent}>
720
+ <div className={getStyles().detailsHeader}>Loader Data</div>
721
+ <div className={getStyles().detailsContent}>
720
722
  <Explorer
721
723
  label="loaderData"
722
724
  value={activeMatch.loaderData}
@@ -725,16 +727,16 @@ export const TanStackRouterDevtoolsPanel = React.forwardRef<
725
727
  </div>
726
728
  </>
727
729
  ) : null}
728
- <div className={styles.detailsHeader}>Explorer</div>
729
- <div className={styles.detailsContent}>
730
+ <div className={getStyles().detailsHeader}>Explorer</div>
731
+ <div className={getStyles().detailsContent}>
730
732
  <Explorer label="Match" value={activeMatch} defaultExpanded={{}} />
731
733
  </div>
732
734
  </div>
733
735
  ) : null}
734
736
  {hasSearch ? (
735
- <div className={styles.fourthContainer}>
736
- <div className={styles.detailsHeader}>Search Params</div>
737
- <div className={styles.detailsContent}>
737
+ <div className={getStyles().fourthContainer}>
738
+ <div className={getStyles().detailsHeader}>Search Params</div>
739
+ <div className={getStyles().detailsContent}>
738
740
  <Explorer
739
741
  value={routerState.location.search || {}}
740
742
  defaultExpanded={Object.keys(
@@ -786,7 +788,7 @@ function AgeTicker({ match }: { match?: AnyRouteMatch }) {
786
788
  route.options.gcTime ?? router.options.defaultGcTime ?? 30 * 60 * 1000
787
789
 
788
790
  return (
789
- <div className={cx(styles.ageTicker(age > staleTime))}>
791
+ <div className={cx(getStyles().ageTicker(age > staleTime))}>
790
792
  <div>{formatTime(age)}</div>
791
793
  <div>/</div>
792
794
  <div>{formatTime(staleTime)}</div>
@@ -1378,4 +1380,11 @@ const stylesFactory = () => {
1378
1380
  }
1379
1381
  }
1380
1382
 
1381
- const styles = stylesFactory()
1383
+ let _styles: ReturnType<typeof stylesFactory> | null = null
1384
+
1385
+ function getStyles() {
1386
+ if (_styles) return _styles
1387
+ _styles = stylesFactory()
1388
+
1389
+ return _styles
1390
+ }