From f8b5a8133ebb2f415a1748e5b1d92647d6033072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sat, 26 Oct 2024 16:15:53 +0200 Subject: [PATCH] initial commit --- shared/naturalcrit/splitPane/splitPane.jsx | 284 ++++++++------------ shared/naturalcrit/splitPane/splitPane.less | 3 + 2 files changed, 118 insertions(+), 169 deletions(-) diff --git a/shared/naturalcrit/splitPane/splitPane.jsx b/shared/naturalcrit/splitPane/splitPane.jsx index 23ae5d321..60fc5c997 100644 --- a/shared/naturalcrit/splitPane/splitPane.jsx +++ b/shared/naturalcrit/splitPane/splitPane.jsx @@ -1,200 +1,146 @@ require('./splitPane.less'); const React = require('react'); -const createClass = require('create-react-class'); +const { useState, useEffect, useRef } = React; const cx = require('classnames'); -const SplitPane = createClass({ - displayName : 'SplitPane', - getDefaultProps : function() { - return { - storageKey : 'naturalcrit-pane-split', - onDragFinish : function(){}, //fires when dragging - showDividerButtons : true - }; - }, +const SplitPane = (props) => { + props = { + storageKey : 'naturalcrit-pane-split', + onDragFinish : function(){}, //fires when dragging + showDividerButtons : true, + ...props + }; + const pane1 = useRef(null); + const pane2 = useRef(null); + const [currentDividerPos, setCurrentDividerPos] = useState(null); + const [userSetDividerPos, setUserSetDividerPos] = useState(null); + const [windowWidth, setWindowWidth] = useState(null); + const [isDragging, setIsDragging] = useState(false); + const [moveSource, setMoveSource] = useState(false); + const [moveBrew, setMoveBrew] = useState(false); + const [showMoveArrows, setShowMoveArrows] = useState(true); + const [liveScroll, setLiveScroll] = useState(false); - getInitialState : function() { - return { - currentDividerPos : null, - windowWidth : 0, - isDragging : false, - moveSource : false, - moveBrew : false, - showMoveArrows : true - }; - }, + const storageKey = props.storageKey || 'naturalcrit-pane-split'; + const onDragFinish = props.onDragFinish || (() => {}); - pane1 : React.createRef(null), - pane2 : React.createRef(null), + // Fetch saved divider position and scroll state on mount + useEffect(() => { + setWindowWidth(window.innerWidth); + const dividerPos = window.localStorage.getItem(storageKey); + const liveScrollSetting = window.localStorage.getItem('liveScroll') === 'true'; + setLiveScroll(liveScrollSetting); - componentDidMount : function() { - const dividerPos = window.localStorage.getItem(this.props.storageKey); - if(dividerPos){ - this.setState({ - currentDividerPos : this.limitPosition(dividerPos, 0.1*(window.innerWidth-13), 0.9*(window.innerWidth-13)), - userSetDividerPos : dividerPos, - windowWidth : window.innerWidth - }); + if (dividerPos) { + const limitedPos = limitPosition(dividerPos, 0.1 * (window.innerWidth - 13), 0.9 * (window.innerWidth - 13)); + setCurrentDividerPos(limitedPos); + setUserSetDividerPos(dividerPos); } else { - this.setState({ - currentDividerPos : window.innerWidth / 2, - userSetDividerPos : window.innerWidth / 2 - }); + setCurrentDividerPos(window.innerWidth / 2); + setUserSetDividerPos(window.innerWidth / 2); } - window.addEventListener('resize', this.handleWindowResize); - // This lives here instead of in the initial render because you cannot touch localStorage until the componant mounts. - const loadLiveScroll = window.localStorage.getItem('liveScroll') === 'true'; - this.setState({ liveScroll: loadLiveScroll }); - }, + const handleResize = () => { + const newPos = limitPosition(userSetDividerPos, 0.1 * (window.innerWidth - 13), 0.9 * (window.innerWidth - 13)); + setCurrentDividerPos(newPos); + setWindowWidth(window.innerWidth); + }; + window.addEventListener('resize', handleResize); - componentWillUnmount : function() { - window.removeEventListener('resize', this.handleWindowResize); - }, + return () => { + window.removeEventListener('resize', handleResize); + }; + }, []); - handleWindowResize : function() { - // Allow divider to increase in size to last user-set position - // Limit current position to between 10% and 90% of visible space - const newLoc = this.limitPosition(this.state.userSetDividerPos, 0.1*(window.innerWidth-13), 0.9*(window.innerWidth-13)); + const limitPosition = (x, min = 1, max = window.innerWidth - 13) => { + return Math.round(Math.min(max, Math.max(min, x))); + }; - this.setState({ - currentDividerPos : newLoc, - windowWidth : window.innerWidth - }); - }, - - limitPosition : function(x, min = 1, max = window.innerWidth - 13) { - const result = Math.round(Math.min(max, Math.max(min, x))); - return result; - }, - - handleUp : function(e){ + const handleUp = (e) => { e.preventDefault(); - if(this.state.isDragging){ - this.props.onDragFinish(this.state.currentDividerPos); - window.localStorage.setItem(this.props.storageKey, this.state.currentDividerPos); + if (isDragging) { + onDragFinish(currentDividerPos); + window.localStorage.setItem(storageKey, currentDividerPos); } - this.setState({ isDragging: false }); - }, + setIsDragging(false); + }; - handleDown : function(e){ + const handleDown = (e) => { e.preventDefault(); - this.setState({ isDragging: true }); - //this.unFocus() - }, - - handleMove : function(e){ - if(!this.state.isDragging) return; + setIsDragging(true); + }; + const handleMove = (e) => { + if (!isDragging) return; e.preventDefault(); - const newSize = this.limitPosition(e.pageX); - this.setState({ - currentDividerPos : newSize, - userSetDividerPos : newSize - }); - }, + const newSize = limitPosition(e.pageX); + setCurrentDividerPos(newSize); + setUserSetDividerPos(newSize); + }; - liveScrollToggle : function() { - window.localStorage.setItem('liveScroll', String(!this.state.liveScroll)); - this.setState({ liveScroll: !this.state.liveScroll }); - }, - /* - unFocus : function() { - if(document.selection){ - document.selection.empty(); - }else{ - window.getSelection().removeAllRanges(); + const liveScrollToggle = () => { + const newScrollState = !liveScroll; + window.localStorage.setItem('liveScroll', String(newScrollState)); + setLiveScroll(newScrollState); + }; + + const renderMoveArrows = () => { + console.log('showMoveArrows: ', showMoveArrows); + if (showMoveArrows) { + return ( + <> +
setMoveSource(!moveSource)}> + +
+
setMoveBrew(!moveBrew)}> + +
+
+ +
+ + ); } - }, - */ + }; - setMoveArrows : function(newState) { - if(this.state.showMoveArrows != newState){ - this.setState({ - showMoveArrows : newState - }); - } - }, - - renderMoveArrows : function(){ - if(this.state.showMoveArrows) { - return <> -
this.setState({ moveSource: !this.state.moveSource })} > - -
-
this.setState({ moveBrew: !this.state.moveBrew })} > - -
-
- -
- ; - } - }, - - renderDivider : function(){ - return <> - {this.props.showDividerButtons && this.renderMoveArrows()} -
-
- - - -
+ const renderDivider = () => ( +
+ {props.showDividerButtons && renderMoveArrows()} +
+ + +
- ; - }, +
+ ); - render : function(){ - return
- - {React.cloneElement(this.props.children[0], { - ...(this.props.showDividerButtons && { - moveBrew : this.state.moveBrew, - moveSource : this.state.moveSource, - liveScroll : this.state.liveScroll, - setMoveArrows : this.setMoveArrows, + return ( +
+ + {React.cloneElement(props.children[0], { + ...(props.showDividerButtons && { + moveBrew, + moveSource, + liveScroll, + setMoveArrows: setShowMoveArrows, }), })} - {this.renderDivider()} - {this.props.children[1]} -
; - } -}); + {renderDivider()} + {props.children[1]} +
+ ); +}; -const Pane = createClass({ - displayName : 'Pane', - getDefaultProps : function() { - return { - width : null - }; - }, - render : function(){ - let styles = {}; - if(this.props.width){ - styles = { - flex : 'none', - width : `${this.props.width}px` - }; - } else { - styles = { - pointerEvents : this.props.isDragging ? 'none' : 'auto' //Disable mouse capture in the rightmost pane; dragging into the iframe drops the divider otherwise - }; - } +const Pane = ({ width, children, isDragging, className }) => { + const styles = width + ? { flex: 'none', width: `${width}px` } + : { pointerEvents: isDragging ? 'none' : 'auto' }; - return
- {this.props.children} -
; - } -}); + return
{children}
; +}; module.exports = SplitPane; diff --git a/shared/naturalcrit/splitPane/splitPane.less b/shared/naturalcrit/splitPane/splitPane.less index e5b3dd7f8..ba85dc3a7 100644 --- a/shared/naturalcrit/splitPane/splitPane.less +++ b/shared/naturalcrit/splitPane/splitPane.less @@ -11,6 +11,7 @@ flex : 1; } .divider{ + position:relative; touch-action : none; display : table; height : 100%; @@ -35,6 +36,8 @@ } .arrow{ position : absolute; + left:50%; + translate:-50%; width : 25px; height : 25px; border : 2px solid #bbb;