11import UplotReact from "../../../uplotReact/UplotReact" ;
22import AutoSizer from "react-virtualized-auto-sizer" ;
3- import { useCallback , useMemo , useRef } from "react" ;
3+ import { useCallback , useEffect , useMemo , useRef } from "react" ;
44import type uPlot from "uplot" ;
55import { chartAxisColor , gridLineColor , gridTicksColor } from "../../../colors" ;
66import type { AlignedData } from "uplot" ;
77import { xRangeMs } from "./const" ;
88import { shredsProgressionPlugin } from "./shredsProgressionPlugin" ;
9- import { useRafLoop } from "react-use" ;
9+ import { useMedia , useRafLoop } from "react-use" ;
1010import { Box } from "@radix-ui/themes" ;
1111
1212const REDRAW_INTERVAL_MS = 40 ;
13+
1314// prevent x axis tick labels from being cut off
1415const chartXPadding = 15 ;
15- const chartData : AlignedData = [ [ - xRangeMs , 0 ] , new Array ( 2 ) ] ;
1616
17- const minXIncrement = 1600 ;
18- const getXIncrs = ( ) => {
19- const incrs = [ minXIncrement ] ;
20- while ( incrs [ incrs . length - 1 ] < xRangeMs ) {
17+ const minXIncrRange = {
18+ min : 200 ,
19+ max : 1_600 ,
20+ } ;
21+
22+ /**
23+ * Get dynamic x axis tick increments based on chart scale
24+ */
25+ const getXIncrs = ( scale : number ) => {
26+ const scaledIncr = scale * minXIncrRange . max ;
27+ // round to multiples of minimum increment
28+ const minIncrMultiple =
29+ Math . trunc ( scaledIncr / minXIncrRange . min ) * minXIncrRange . min ;
30+
31+ const incrs = [ minIncrMultiple ] ;
32+ while ( incrs [ incrs . length - 1 ] < xRangeMs * scale ) {
2133 incrs . push ( incrs [ incrs . length - 1 ] * 2 ) ;
2234 }
2335 return incrs ;
2436} ;
25- const xIncrs = getXIncrs ( ) ;
2637
2738interface ShredsChartProps {
2839 chartId : string ;
@@ -32,13 +43,46 @@ export default function ShredsChart({
3243 chartId,
3344 isOnStartupScreen,
3445} : ShredsChartProps ) {
46+ const isXL = useMedia ( "(max-width: 2100px)" ) ;
47+ const isL = useMedia ( "(max-width: 1800px)" ) ;
48+ const isM = useMedia ( "(max-width: 1500px)" ) ;
49+ const isS = useMedia ( "(max-width: 1200px)" ) ;
50+ const isXS = useMedia ( "(max-width: 900px)" ) ;
51+ const isXXS = useMedia ( "(max-width: 600px)" ) ;
52+ const scale = isXXS
53+ ? 1 / 7
54+ : isXS
55+ ? 2 / 7
56+ : isS
57+ ? 3 / 7
58+ : isM
59+ ? 4 / 7
60+ : isL
61+ ? 5 / 7
62+ : isXL
63+ ? 6 / 7
64+ : 1 ;
65+
3566 const uplotRef = useRef < uPlot > ( ) ;
3667 const lastRedrawRef = useRef ( 0 ) ;
3768
3869 const handleCreate = useCallback ( ( u : uPlot ) => {
3970 uplotRef . current = u ;
4071 } , [ ] ) ;
4172
73+ const [ chartData , xIncrs ] = useMemo ( ( ) => {
74+ return [
75+ [ [ Math . trunc ( scale * - xRangeMs ) , 0 ] , new Array ( 2 ) ] satisfies AlignedData ,
76+ getXIncrs ( scale ) ,
77+ ] ;
78+ } , [ scale ] ) ;
79+
80+ useEffect ( ( ) => {
81+ if ( ! uplotRef . current ) return ;
82+ uplotRef . current . axes [ 0 ] . incrs = ( ) => xIncrs ;
83+ uplotRef . current . setData ( chartData , true ) ;
84+ } , [ chartData , xIncrs ] ) ;
85+
4286 const options = useMemo < uPlot . Options > ( ( ) => {
4387 return {
4488 padding : [ 0 , chartXPadding , 0 , chartXPadding ] ,
@@ -94,7 +138,7 @@ export default function ShredsChart({
94138 ] ,
95139 plugins : [ shredsProgressionPlugin ( isOnStartupScreen ) ] ,
96140 } ;
97- } , [ isOnStartupScreen ] ) ;
141+ } , [ isOnStartupScreen , xIncrs ] ) ;
98142
99143 useRafLoop ( ( time : number ) => {
100144 if ( ! uplotRef ) return ;
0 commit comments