import React , { useRef , forwardRef , useContext , useEffect } from 'react' ; var __assign = function ( ) { __assign = Object . assign || function __assign ( t ) { for ( var s , i = 1 , n = arguments . length ; i < n ; i ++ ) { s = arguments [ i ] ; for ( var p in s ) if ( Object . prototype . hasOwnProperty . call ( s , p ) ) t [ p ] = s [ p ] ; } return t ; } ; return __assign . apply ( this , arguments ) ; } ; /**
 * ScrollingSyncerContext is the context to be handling scrolled nodes
 */ var ScrollingSyncerContext = React . createContext ( { registerNode : function ( _node , _group ) { } , unregisterNode : function ( _node , _group ) { } , onScroll : function ( _e , _groups ) { } , } ) ; param props var ScrollSync = function ( props ) { /**
     * a map of group: and it's nodes
     * {
     *  groupA: [node1, node2, node3],
     *  groupB: [node4, node5],
     *  groupC: [node1, node4],
     * }
     */ var nodesRef = useRef ( { } ) ; var elements = nodesRef . current ; /**
     * A simple trick to avoid calling `requestAnimationFrame` before the frame is painted, to enhance performance!
     */ var shouldPaintFrameRef = useRef ( true ) ; var shouldPaintFrame = shouldPaintFrameRef . current ; param group var findGroup = function ( group ) { return ! ! elements [ group ] ; } ; param node param group var doesNodeExists = function ( node , group ) { var groupExists = findGroup ( group ) ; if ( ! groupExists ) return false ; var foundNode = elements [ group ] . find ( function ( element ) { return element . node === node ; } ) ; if ( ! foundNode ) return false ; return ! ! foundNode ; } ; param node param groups var registerNode = function ( element , groups ) { groups . forEach ( function ( group ) { var groupExists = findGroup ( group ) ; if ( ! groupExists ) { elements [ group ] = [ ] ; } elements [ group ] . push ( __assign ( { } , element ) ) ; } ) ; } ; param element param groups var unregisterNode = function ( element , groups ) { groups . forEach ( function ( group ) { var doesNodeExist = doesNodeExists ( element . node , group ) ; if ( doesNodeExist ) { elements [ group ] . splice ( elements [ group ] . findIndex ( function ( e ) { return element . node === e . node ; } ) , 1 ) ; } } ) ; } ; param scrolledNode param node var syncScrollPosition = function ( scrolledNode , node ) { if ( ! scrolledNode || ! node ) return ; var scrollTop = scrolledNode . scrollTop , scrollHeight = scrolledNode . scrollHeight , offsetHeight = scrolledNode . offsetHeight , scrollLeft = scrolledNode . scrollLeft , scrollWidth = scrolledNode . scrollWidth , offsetLeft = scrolledNode . offsetLeft , offsetWidth = scrolledNode . offsetWidth ; if ( ! props . proportional ) { node . scrollLeft = scrollLeft ; node . scrollTop = scrollTop ; return ; } var percentagePerHeight = scrollTop / ( scrollHeight - offsetHeight ) ; var percentagePerWidth = scrollLeft / ( scrollWidth - offsetWidth ) ; node . scrollTop = Math . round ( percentagePerHeight * ( node . scrollHeight - node . offsetHeight ) ) ; node . scrollLeft = Math . round ( percentagePerWidth * ( node . scrollWidth - node . offsetWidth ) ) ; } ; param scrolledNode param groups var syncScrollPositions = function ( scrolledNode , groups ) { groups . forEach ( function ( group ) { elements [ group ] . forEach ( function ( element ) { if ( scrolledNode !== element . node ) { var isEnabled = element . scroll === "two-way" ; var isSynced = element . scroll === "synced-only" ; ( isEnabled || isSynced ) && syncScrollPosition ( scrolledNode , element . node ) ; } } ) ; } ) ; } ; param node param groups var handleNodeScroll = function ( node , groups ) { if ( shouldPaintFrame ) { window . requestAnimationFrame ( function ( ) { syncScrollPositions ( node , groups ) ; shouldPaintFrame = true ; } ) ; shouldPaintFrame = false ; } } ; return ( React . createElement ( ScrollingSyncerContext . Provider , { value : { registerNode : registerNode , unregisterNode : unregisterNode , onScroll : function ( e , groups ) { return ! props . disabled && handleNodeScroll ( e . currentTarget , groups ) ; } , } } , React . Children . only ( props . children ) ) ) ; } ; ScrollSync . defaultProps = { disabled : false , proportional : true , } ; var toArray = function ( groups ) { return [ ] . concat ( groups ) ; } ; var getMovingAxis = function ( e ) { if ( e . deltaX > 0 || e . deltaX < 0 ) return "X" ; if ( e . deltaY > 0 || e . deltaY < 0 ) return "Y" ; if ( ( e . deltaY > 0 || e . deltaY < 0 ) && ( e . deltaX > 0 || e . deltaX < 0 ) ) return "XY" ; return null ; } ; var ScrollSyncNode = forwardRef ( function ( props , forwardedRef ) { var children = props . children , _a = props . group , group = _a === void 0 ? "default" : _a , _b = props . scroll , scroll = _b === void 0 ? "two-way" : _b , _c = props . selfLockAxis , selfLockAxis = _c === void 0 ? null : _c , _d = props . onScroll , onNodeScroll = _d === void 0 ? function ( ) { return undefined ; } : _d ; var _e = useContext ( ScrollingSyncerContext ) , registerNode = _e . registerNode , unregisterNode = _e . unregisterNode , onScroll = _e . onScroll ; var childRef = children . ref ; var hasDoubleRef = childRef != null && forwardedRef != null ; if ( hasDoubleRef ) { console . warn ( "scroll-sync-react:\nWARNING: ref used on both ScrollSyncNode and its direct child.\nUsing the ref from the ScrollSyncNode component." ) ; } var ref = childRef && ! forwardedRef ? childRef : useRef ( null ) ; useEffect ( function ( ) { if ( typeof forwardedRef === "function" ) { forwardedRef ( ref . current ) ; } } , [ ] ) ; var applySelfLockAxis = function ( event ) { var movingAxis = getMovingAxis ( event ) ; if ( selfLockAxis === "X" && movingAxis === "X" ) { event . preventDefault ( ) ; } else if ( selfLockAxis === "Y" && movingAxis === "Y" ) { event . preventDefault ( ) ; } else if ( selfLockAxis === "XY" && ( movingAxis === "XY" || movingAxis === "X" || movingAxis === "Y" ) ) { event . preventDefault ( ) ; } } ; useEffect ( function ( ) { var _a ; var syncableElement = { node : ref . current , scroll : scroll } ; if ( syncableElement ) registerNode ( syncableElement , toArray ( group ) ) ; ( _a = ref . current ) === null || _a === void 0 ? void 0 : _a . addEventListener ( "wheel" , applySelfLockAxis , { passive : false } ) ; return function ( ) { var _a ; unregisterNode ( syncableElement , toArray ( group ) ) ; ( _a = ref . current ) === null || _a === void 0 ? void 0 : _a . removeEventListener ( "wheel" , applySelfLockAxis ) ; } ; } , [ ] ) ; useEffect ( function ( ) { var syncableElement = { node : ref . current , scroll : scroll } ; unregisterNode ( syncableElement , toArray ( group ) ) ; registerNode ( syncableElement , toArray ( group ) ) ; return function ( ) { return unregisterNode ( syncableElement , toArray ( group ) ) ; } ; } , [ scroll , group ] ) ; var isSyncer = scroll === "syncer-only" ; var isEnabled = scroll === "two-way" ; return React . cloneElement ( children , { ref : ref , onScroll : function ( e ) { if ( typeof children . props . onScroll === "function" ) { children . props . onScroll ( e ) ; } e . persist ( ) ; if ( isSyncer || isEnabled ) { onScroll ( e , toArray ( group ) ) ; onNodeScroll ( e ) ; } } , onWheel : function ( e ) { if ( typeof children . props . onWheel === "function" ) { children . props . onWheel ( e ) ; } e . persist ( ) ; if ( isSyncer || isEnabled ) { onScroll ( e , toArray ( group ) ) ; onNodeScroll ( e ) ; } } , } ) ; } ) ; ScrollSyncNode . displayName = "ScrollSyncNode" ; export { ScrollSync , ScrollSyncNode } ;