22import { Column , Grid , Heading , Loading , Row , Switch , Text } from '@umami/react-zen' ;
33import { useCallback , useEffect , useMemo , useRef , useState } from 'react' ;
44import { LoadingPanel } from '@/components/common/LoadingPanel' ;
5- import { useMessages , useResultQuery } from '@/components/hooks' ;
5+ import { useResultQuery } from '@/components/hooks' ;
66import { useReplayQuery } from '@/components/hooks/queries/useReplayQuery' ;
77import { formatLongNumber } from '@/lib/format' ;
88import type { HeatmapMode , HeatmapPoint , HeatmapResult , HeatmapSnapshot } from '@/queries/sql' ;
@@ -115,6 +115,14 @@ export function Heatmap({ websiteId, urlPath, onUrlPathChange, mode, search }: H
115115 onUrlPathChange ( filteredPages [ 0 ] . urlPath ) ;
116116 } , [ filteredPages , isLoading , onUrlPathChange , urlPath ] ) ;
117117
118+ if ( ! isLoading && pages . length === 0 ) {
119+ return (
120+ < LoadingPanel data = { pagesData } isLoading = { isLoading } error = { error } minHeight = "900px" >
121+ < EmptyState message = "No data available." />
122+ </ LoadingPanel >
123+ ) ;
124+ }
125+
118126 return (
119127 < LoadingPanel data = { pagesData } isLoading = { isLoading } error = { error } minHeight = "900px" >
120128 < Grid columns = "320px 12px 1fr" minHeight = "900px" className = { styles . layoutGrid } >
@@ -167,15 +175,11 @@ function PageList({
167175 mode : HeatmapMode ;
168176 hasSearch : boolean ;
169177} ) {
170- const { t, messages } = useMessages ( ) ;
171-
172178 return (
173179 < Column className = { styles . pageList } gap = "1" >
174180 < Heading size = "lg" > Pages</ Heading >
175181 < Column className = { styles . pageListItems } gap = "2" >
176- { pages . length === 0 && (
177- < Text color = "muted" > { hasSearch ? 'No matching pages' : t ( messages . noDataAvailable ) } </ Text >
178- ) }
182+ { pages . length === 0 && hasSearch && < Text color = "muted" > No matching pages</ Text > }
179183 { pages . map ( p => (
180184 < button
181185 key = { p . urlPath }
@@ -295,29 +299,29 @@ function HeatmapView({
295299 onReady = { handleSnapshotReady }
296300 />
297301 ) }
302+ { showOverlay && (
303+ < div className = { styles . overlay } >
304+ { visible . map ( ( p , i ) => {
305+ const intensity = Math . min ( 1 , p . count / maxCount ) ;
306+ const size = 24 + intensity * 36 ;
307+ return (
308+ < div
309+ key = { `${ p . x } -${ p . y } -${ i } ` }
310+ className = { styles . dot }
311+ style = { {
312+ left : p . x * scale - size / 2 ,
313+ top : p . y * scale - size / 2 ,
314+ width : size ,
315+ height : size ,
316+ opacity : 0.25 + intensity * 0.55 ,
317+ } }
318+ title = { `${ p . count } click${ p . count === 1 ? '' : 's' } ` }
319+ />
320+ ) ;
321+ } ) }
322+ </ div >
323+ ) }
298324 </ div >
299- { showOverlay && (
300- < div className = { `${ styles . overlay } ${ styles . heatOverlay } ` } >
301- { visible . map ( ( p , i ) => {
302- const intensity = Math . min ( 1 , p . count / maxCount ) ;
303- const size = 24 + intensity * 36 ;
304- return (
305- < div
306- key = { `${ p . x } -${ p . y } -${ i } ` }
307- className = { styles . dot }
308- style = { {
309- left : p . x * scale - size / 2 ,
310- top : p . y * scale - size / 2 ,
311- width : size ,
312- height : size ,
313- opacity : 0.25 + intensity * 0.55 ,
314- } }
315- title = { `${ p . count } click${ p . count === 1 ? '' : 's' } ` }
316- />
317- ) ;
318- } ) }
319- </ div >
320- ) }
321325 </ div >
322326 </ div >
323327 { snapshot && (
@@ -560,12 +564,8 @@ function ReplaySnapshot({
560564 void finalize ( ) ;
561565 } ) ;
562566
563- replayer . on ( 'resize' , ( dimension : { width ?: number ; height ?: number } ) => {
564- resizeReplayFrame (
565- replayer ,
566- dimension . width && Number . isFinite ( dimension . width ) ? dimension . width : width ,
567- dimension . height && Number . isFinite ( dimension . height ) ? dimension . height : height ,
568- ) ;
567+ replayer . on ( 'resize' , ( ) => {
568+ resizeReplayFrame ( replayer , width , height ) ;
569569 } ) ;
570570
571571 setTimeout ( ( ) => {
@@ -661,6 +661,12 @@ function resizeReplayFrame(replayer: ReplayInstance, width: number, height: numb
661661 if ( wrapper ) {
662662 wrapper . style . width = `${ width } px` ;
663663 wrapper . style . height = `${ height } px` ;
664+ wrapper . style . minWidth = `${ width } px` ;
665+ wrapper . style . minHeight = `${ height } px` ;
666+ wrapper . style . maxWidth = `${ width } px` ;
667+ wrapper . style . maxHeight = `${ height } px` ;
668+ wrapper . style . margin = '0' ;
669+ wrapper . style . padding = '0' ;
664670 wrapper . style . overflow = 'hidden' ;
665671 }
666672
@@ -669,6 +675,11 @@ function resizeReplayFrame(replayer: ReplayInstance, width: number, height: numb
669675 iframe . setAttribute ( 'height' , String ( height ) ) ;
670676 iframe . style . width = `${ width } px` ;
671677 iframe . style . height = `${ height } px` ;
678+ iframe . style . minWidth = `${ width } px` ;
679+ iframe . style . minHeight = `${ height } px` ;
680+ iframe . style . maxWidth = `${ width } px` ;
681+ iframe . style . maxHeight = `${ height } px` ;
682+ iframe . style . margin = '0' ;
672683 iframe . style . display = 'block' ;
673684 }
674685
@@ -678,7 +689,7 @@ function resizeReplayFrame(replayer: ReplayInstance, width: number, height: numb
678689function EmptyState ( { message } : { message ?: string } = { } ) {
679690 return (
680691 < Column alignItems = "center" justifyContent = "center" minHeight = "360px" gap >
681- < Heading size = "lg" > { message ? 'No data' : ' Select a page' } </ Heading >
692+ { ! message && < Heading size = "lg" > Select a page</ Heading > }
682693 < Text color = "muted" > { message ?? 'Choose a page from the list to view its heatmap.' } </ Text >
683694 </ Column >
684695 ) ;
0 commit comments