@@ -19,7 +19,12 @@ import {
1919} from 'react'
2020import styled , { useTheme } from 'styled-components'
2121
22- import { InfoOutlineIcon , Tooltip , WrapWithIf } from '../../index'
22+ import {
23+ InfoOutlineIcon ,
24+ Tooltip ,
25+ useResizeObserver ,
26+ WrapWithIf ,
27+ } from '../../index'
2328import Button from '../Button'
2429import EmptyState from '../EmptyState'
2530import CaretUpIcon from '../icons/CaretUpIcon'
@@ -44,15 +49,17 @@ import {
4449 TableProps ,
4550} from './tableUtils'
4651import { Tbody } from './Tbody'
47- import { Td , TdBasic , TdExpand , TdLoading } from './Td'
52+ import { Td , TdBasic , TdExpand , TdGhostLink , TdLoading } from './Td'
4853import { Th } from './Th'
4954import { Thead } from './Thead'
5055import { Tr } from './Tr'
5156
57+ const GHOST_LINK_ID = 'ghost-link'
58+
5259function Table ( {
5360 ref : forwardedRef ,
5461 data,
55- columns,
62+ columns : columnsProp ,
5663 loading = false ,
5764 loadingSkeletonRows = 10 ,
5865 hideHeader = false ,
@@ -74,6 +81,7 @@ function Table({
7481 reactTableOptions,
7582 highlightedRowId,
7683 onRowClick,
84+ getRowLink,
7785 emptyStateProps,
7886 hasNextPage,
7987 isFetchingNextPage,
@@ -84,10 +92,18 @@ function Table({
8492} : TableProps ) {
8593 const theme = useTheme ( )
8694 const tableContainerRef = useRef < HTMLDivElement > ( undefined )
95+
96+ const [ tableWidth , setTableWidth ] = useState ( 0 )
97+ useResizeObserver ( tableContainerRef , ( entry ) => setTableWidth ( entry . width ) )
98+
8799 const [ hover , setHover ] = useState ( false )
88100 const [ scrollTop , setScrollTop ] = useState ( 0 )
89101 const [ expanded , setExpanded ] = useState ( { } )
90102
103+ const columns = useMemo ( ( ) => {
104+ return [ ...columnsProp , ...( ! ! getRowLink ? [ { id : GHOST_LINK_ID } ] : [ ] ) ]
105+ } , [ columnsProp , getRowLink ] )
106+
91107 const table = useReactTable ( {
92108 data,
93109 columns,
@@ -245,50 +261,54 @@ function Table({
245261 key = { headerGroup . id }
246262 $fillLevel = { fillLevel }
247263 >
248- { headerGroup . headers . map ( ( header ) => (
249- < Th
250- key = { header . id }
251- $fillLevel = { fillLevel }
252- $hideHeader = { hideHeader }
253- $stickyColumn = { stickyColumn }
254- $highlight = { header . column . columnDef ?. meta ?. highlight }
255- { ...( header . column . getCanSort ( )
256- ? {
257- $cursor :
258- header . column . getIsSorted ( ) === 'asc'
259- ? 's-resize'
260- : header . column . getIsSorted ( ) === 'desc'
261- ? 'ns-resize'
262- : 'n-resize' ,
263- onClick : header . column . getToggleSortingHandler ( ) ,
264- }
265- : { } ) }
266- >
267- < div className = "thOuterWrap" >
268- < div className = "thSortIndicatorWrap" >
269- < div >
270- { header . isPlaceholder
271- ? null
272- : flexRender (
273- header . column . columnDef . header ,
274- header . getContext ( )
275- ) }
264+ { headerGroup . headers . map ( ( header ) =>
265+ header . column . id . includes ( GHOST_LINK_ID ) ? (
266+ < th key = { header . id } />
267+ ) : (
268+ < Th
269+ key = { header . id }
270+ $fillLevel = { fillLevel }
271+ $hideHeader = { hideHeader }
272+ $stickyColumn = { stickyColumn }
273+ $highlight = { header . column . columnDef ?. meta ?. highlight }
274+ { ...( header . column . getCanSort ( )
275+ ? {
276+ $cursor :
277+ header . column . getIsSorted ( ) === 'asc'
278+ ? 's-resize'
279+ : header . column . getIsSorted ( ) === 'desc'
280+ ? 'ns-resize'
281+ : 'n-resize' ,
282+ onClick : header . column . getToggleSortingHandler ( ) ,
283+ }
284+ : { } ) }
285+ >
286+ < div className = "thOuterWrap" >
287+ < div className = "thSortIndicatorWrap" >
288+ < div >
289+ { header . isPlaceholder
290+ ? null
291+ : flexRender (
292+ header . column . columnDef . header ,
293+ header . getContext ( )
294+ ) }
295+ </ div >
296+ { header . column . columnDef . meta ?. tooltip && (
297+ < Tooltip
298+ label = { header . column . columnDef . meta . tooltip }
299+ { ...header . column . columnDef . meta . tooltipProps }
300+ >
301+ < InfoOutlineIcon />
302+ </ Tooltip >
303+ ) }
304+ < SortIndicator
305+ direction = { header . column . getIsSorted ( ) }
306+ />
276307 </ div >
277- { header . column . columnDef . meta ?. tooltip && (
278- < Tooltip
279- label = { header . column . columnDef . meta . tooltip }
280- { ...header . column . columnDef . meta . tooltipProps }
281- >
282- < InfoOutlineIcon />
283- </ Tooltip >
284- ) }
285- < SortIndicator
286- direction = { header . column . getIsSorted ( ) }
287- />
288308 </ div >
289- </ div >
290- </ Th >
291- ) ) }
309+ </ Th >
310+ )
311+ ) }
292312 </ Tr >
293313 ) ) }
294314 </ Thead >
@@ -358,7 +378,7 @@ function Table({
358378 $highlighted = { tableRow ?. id === highlightedRowId }
359379 $selectable = { tableRow ?. getCanSelect ( ) ?? false }
360380 $selected = { tableRow ?. getIsSelected ( ) ?? false }
361- $clickable = { ! ! onRowClick }
381+ $clickable = { ! ! onRowClick || ! ! getRowLink }
362382 >
363383 { isNil ( tableRow ) && isLoaderRow ? (
364384 < TdLoading
@@ -376,28 +396,37 @@ function Table({
376396 < Spinner color = { theme . colors [ 'text-xlight' ] } />
377397 </ TdLoading >
378398 ) : (
379- tableRow ?. getVisibleCells ( ) . map ( ( cell ) => (
380- < Td
381- key = { cell . id }
382- $fillLevel = { fillLevel }
383- $firstRow = { i === 0 }
384- $padCells = { padCells }
385- $loose = { loose }
386- $stickyColumn = { stickyColumn }
387- $highlight = {
388- cell . column ?. columnDef ?. meta ?. highlight
389- }
390- $truncateColumn = {
391- cell . column ?. columnDef ?. meta ?. truncate
392- }
393- $center = { cell . column ?. columnDef ?. meta ?. center }
394- >
395- { flexRender (
396- cell . column . columnDef . cell ,
397- cell . getContext ( )
398- ) }
399- </ Td >
400- ) )
399+ tableRow ?. getVisibleCells ( ) . map ( ( cell ) =>
400+ cell . id . includes ( GHOST_LINK_ID ) ? (
401+ < TdGhostLink
402+ key = { cell . id }
403+ width = { tableWidth }
404+ href = { getRowLink ?.( tableRow ) }
405+ />
406+ ) : (
407+ < Td
408+ key = { cell . id }
409+ $fillLevel = { fillLevel }
410+ $firstRow = { i === 0 }
411+ $padCells = { padCells }
412+ $loose = { loose }
413+ $stickyColumn = { stickyColumn }
414+ $highlight = {
415+ cell . column ?. columnDef ?. meta ?. highlight
416+ }
417+ $truncateColumn = {
418+ cell . column ?. columnDef ?. meta ?. truncate
419+ }
420+ $center = { cell . column ?. columnDef ?. meta ?. center }
421+ $rowsHaveLinks = { ! ! getRowLink }
422+ >
423+ { flexRender (
424+ cell . column . columnDef . cell ,
425+ cell . getContext ( )
426+ ) }
427+ </ Td >
428+ )
429+ )
401430 ) }
402431 </ Tr >
403432 { tableRow ?. getIsExpanded ( ) && (
@@ -454,7 +483,7 @@ function Table({
454483 small
455484 floating
456485 width = { 140 }
457- css = { { position : 'absolute' , right : 24 , bottom : 24 } }
486+ css = { { position : 'absolute' , right : 24 , bottom : 24 , zIndex : 1 } }
458487 endIcon = { < CaretUpIcon /> }
459488 onClick = { ( ) =>
460489 tableContainerRef ?. current ?. scrollTo ( {
0 commit comments