11// Tabletable - Copyright 2020 Zeroarc Software, LLC
22'use strict' ;
33
4- import React , { useState , ReactElement , SyntheticEvent , FunctionComponent , useEffect } from 'react' ;
4+ import React , { useState , ReactElement , SyntheticEvent , FunctionComponent , useEffect , useRef , useCallback } from 'react' ;
55import Immutable from 'immutable' ;
66import ClassNames from 'classnames' ;
77// Fonts
88import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' ;
99import { library } from '@fortawesome/fontawesome-svg-core' ;
10- import { faSort } from '@fortawesome/free-solid-svg-icons/faSort' ;
10+ import { faSort } from '@fortawesome/free-solid-svg-icons/faSort' ;
1111import { faTimes } from '@fortawesome/free-solid-svg-icons/faTimes' ;
1212import { faSearch } from '@fortawesome/free-solid-svg-icons/faSearch' ;
1313import { faSortDown } from '@fortawesome/free-solid-svg-icons/faSortDown' ;
@@ -87,9 +87,21 @@ const TabletableContainer: FunctionComponent<Props> = ({
8787} ) => {
8888
8989 const [ formFilterValue , setFilterValue ] = useState ( filterValue ) ;
90+ const [ tableWidth , setTableWidth ] = useState ( 0 ) ;
91+
92+ const responsiveTableRef = useRef < HTMLDivElement | null > ( null ) ;
93+ const scrollerRef = useRef < HTMLDivElement | null > ( null ) ;
94+ const scrollLock = useRef ( false ) ;
95+
96+ const callbackTableRef = useCallback ( node => {
97+ if ( node !== null ) {
98+ responsiveTableRef . current = node ;
99+ setTableWidth ( node . scrollWidth + 5 ) ;
100+ }
101+ } , [ ] ) ;
90102
91103 // Track filterValue changes and reset the state to the passed in value
92- // if it changes
104+ // if it changes.
93105 useEffect ( ( ) => {
94106 setFilterValue ( filterValue ) ;
95107 } , [ filterValue ] ) ;
@@ -139,6 +151,28 @@ const TabletableContainer: FunctionComponent<Props> = ({
139151 }
140152 } ;
141153
154+ // Keep top scroll controller and master table scrollbar on bottom in sync.
155+ const handleScrollControlScroll = ( e : React . UIEvent < HTMLElement > ) : void => {
156+ if ( responsive && ! scrollLock . current && responsiveTableRef ?. current ) {
157+ scrollLock . current = true ;
158+ responsiveTableRef . current . scrollLeft = e . currentTarget . scrollLeft ;
159+
160+ setTimeout ( ( ) => {
161+ scrollLock . current = false ;
162+ } , 1 ) ;
163+ }
164+ }
165+ const handleTableScroll = ( e : React . UIEvent < HTMLElement > ) : void => {
166+ if ( responsive && ! scrollLock . current && scrollerRef ?. current ) {
167+ scrollLock . current = true ;
168+ scrollerRef . current . scrollLeft = e . currentTarget . scrollLeft ;
169+
170+ setTimeout ( ( ) => {
171+ scrollLock . current = false ;
172+ } , 10 ) ;
173+ }
174+ }
175+
142176 //#endregion
143177
144178 if ( ! Immutable . isImmutable ( data ) ) {
@@ -260,7 +294,6 @@ const TabletableContainer: FunctionComponent<Props> = ({
260294 } ) ;
261295
262296 let createRow : JSX . Element | null = null ;
263- let createActionsRow : JSX . Element | null = null ;
264297 let errorMsg : JSX . Element | null = null ;
265298
266299 if ( mode === 'create' ) {
@@ -411,6 +444,12 @@ const TabletableContainer: FunctionComponent<Props> = ({
411444 )
412445 : '' ;
413446
447+ const scrollControl = (
448+ < div className = "scroll-control mb-3" onScroll = { handleScrollControlScroll } ref = { scrollerRef } >
449+ < div id = "scroller" style = { { width : tableWidth } } > </ div >
450+ </ div >
451+ ) ;
452+
414453 return (
415454 < div className = { containerCssClass } >
416455 < div className = 'row' >
@@ -423,7 +462,9 @@ const TabletableContainer: FunctionComponent<Props> = ({
423462 { showSpinner ? (
424463 spinner
425464 ) : (
426- < div className = { responsive ? 'table-responsive' : '' } >
465+ < >
466+ { responsive ? scrollControl : null }
467+ < div className = { responsive ? 'table-responsive' : '' } ref = { callbackTableRef } onScroll = { handleTableScroll } >
427468 < table className = { tableCssClass } >
428469 < thead >
429470 < tr >
@@ -436,7 +477,8 @@ const TabletableContainer: FunctionComponent<Props> = ({
436477 </ tbody >
437478 </ table >
438479 </ div >
439- )
480+ </ >
481+ )
440482 }
441483 { pager }
442484 </ div >
0 commit comments