From 6f5d8e5c1bd9133ecf0cfaaaf535dacfb8d870f5 Mon Sep 17 00:00:00 2001 From: Hristo Kanchev Date: Fri, 14 Feb 2020 13:30:14 +0100 Subject: [PATCH 01/17] feat: DevTools - Added Resize Support. --- .../devtools/views/Components/Components.css | 27 +++- .../devtools/views/Components/Components.js | 147 +++++++++++++++--- 2 files changed, 148 insertions(+), 26 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Components.css b/packages/react-devtools-shared/src/devtools/views/Components/Components.css index f37b3eaa73d..b1dacee87c2 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Components.css +++ b/packages/react-devtools-shared/src/devtools/views/Components/Components.css @@ -1,4 +1,4 @@ -.Components { +.ComponentsWrapper { position: relative; width: 100%; height: 100%; @@ -15,13 +15,26 @@ } .SelectedElementWrapper { - flex: 0 0 35%; + flex: 1 1 35%; overflow-x: hidden; overflow-y: auto; } +.ResizeBarWrapper { + flex: 0 0 0px; + position: relative; +} + +.ResizeBar { + position: absolute; + left: -2px; + width: 5px; + height: 100%; + cursor: ew-resize; +} + @media screen and (max-width: 600px) { - .Components { + .ComponentsWrapper { flex-direction: column; } @@ -32,6 +45,14 @@ .SelectedElementWrapper { flex: 0 0 50%; } + + .ResizeBar { + top: -2px; + left: 0; + width: 100%; + height: 5px; + cursor: ns-resize; + } } .Loading { diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Components.js b/packages/react-devtools-shared/src/devtools/views/Components/Components.js index 6b65e0d2035..6e84d43fbb4 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Components.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/Components.js @@ -8,7 +8,16 @@ */ import * as React from 'react'; -import {Suspense} from 'react'; +import { + Suspense, + Fragment, + useRef, + useState, + useMemo, + useCallback, + useDebugValue, + useEffect +} from 'react'; import Tree from './Tree'; import SelectedElement from './SelectedElement'; import {InspectedElementContextController} from './InspectedElementContext'; @@ -18,33 +27,125 @@ import portaledContent from '../portaledContent'; import {ModalDialog} from '../ModalDialog'; import SettingsModal from 'react-devtools-shared/src/devtools/views/Settings/SettingsModal'; import {SettingsModalContextController} from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContext'; +import {useLocalStorage} from "../hooks"; import styles from './Components.css'; function Components(_: {||}) { - // TODO Flex wrappers below should be user resizable. - return ( - - - -
-
- -
-
- - }> - - - -
- - -
-
-
-
+ return + + + + {({resizeElementRef, onResizeStart, resizeElementStyles}) => + +
+ +
+
+
+
+
+ + }> + + + +
+ + + } + + + + ; +} + +const resizeDirections = { + HORIZONTAL: 'HORIZONTAL', + VERTICAL: 'VERTICAL', +}; + + +function ComponentResizer({ children }: {| children: React$Node |}) { + const [isResizing, setIsResizing] = useState(false); + const [horizontalPercentage, setHorizontalPercentage] = useLocalStorage( + `React::DevTools::resizedElementPercentage::${resizeDirections.HORIZONTAL}`, + 65, ); + const [verticalPercentage, setVerticalPercentage] = useLocalStorage( + `React::DevTools::resizedElementPercentage::${resizeDirections.VERTICAL}`, + 50, + ); + const updateLocalStorageTimeoutId = useRef(null); + const componentsWrapperRef = useRef(null); + const resizeElementRef = useRef(null); + + const resizeElementStyles = useMemo(() => ({ + flexBasis: `${window.innerWidth > 600 ? horizontalPercentage : verticalPercentage}%`, + }), [horizontalPercentage, verticalPercentage]); + + const onResizeStart = useCallback(() => { + setIsResizing(true); + }, [setIsResizing]); + + const onResizeEnd = useCallback(() => { + setIsResizing(false); + }, [setIsResizing]); + + const onResize = useCallback((e) => { + if (!isResizing || (componentsWrapperRef.current === null || resizeElementRef.current === null)) { + return; + } + + e.preventDefault(); + + const {height, width, left, top} = componentsWrapperRef.current.getBoundingClientRect(); + const resizeDirection = width > 600 ? resizeDirections.HORIZONTAL : resizeDirections.VERTICAL; + const currentMousePosition = resizeDirection === resizeDirections.HORIZONTAL ? (e.clientX - left) : (e.clientY - top); + const boundary = { + min: 40, + max: (resizeDirection === resizeDirections.HORIZONTAL ? width - 40 : height - 40), + }; + const mousePositionInBounds = currentMousePosition > boundary.min && currentMousePosition < boundary.max; + + if (mousePositionInBounds) { + const updatedFlexBasisValue = (currentMousePosition / (resizeDirection === resizeDirections.HORIZONTAL ? width : height)) * 100; + + resizeElementRef.current.style.flexBasis = `${updatedFlexBasisValue}%`; + + clearTimeout(updateLocalStorageTimeoutId.current); + updateLocalStorageTimeoutId.current = setTimeout(() => { + resizeDirection === resizeDirections.HORIZONTAL ? setHorizontalPercentage(updatedFlexBasisValue) : setVerticalPercentage(updatedFlexBasisValue); + }, 500); + } + }, [componentsWrapperRef, resizeElementRef, isResizing]); + + return ( +
+ {children({resizeElementRef, onResizeStart, resizeElementStyles})} +
+ ) } function Loading() { From 65bbec58a3991d63424d3c319fa8ac21641923ab Mon Sep 17 00:00:00 2001 From: Hristo Kanchev Date: Fri, 14 Feb 2020 15:26:43 +0100 Subject: [PATCH 02/17] feat: Prettier. --- .../devtools/views/Components/Components.js | 197 ++++++++++-------- 1 file changed, 115 insertions(+), 82 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Components.js b/packages/react-devtools-shared/src/devtools/views/Components/Components.js index 6e84d43fbb4..77b57928c2c 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Components.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/Components.js @@ -7,16 +7,13 @@ * @flow */ -import * as React from 'react'; -import { +import React, { Suspense, Fragment, useRef, useState, useMemo, useCallback, - useDebugValue, - useEffect } from 'react'; import Tree from './Tree'; import SelectedElement from './SelectedElement'; @@ -27,46 +24,48 @@ import portaledContent from '../portaledContent'; import {ModalDialog} from '../ModalDialog'; import SettingsModal from 'react-devtools-shared/src/devtools/views/Settings/SettingsModal'; import {SettingsModalContextController} from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContext'; -import {useLocalStorage} from "../hooks"; +import {useLocalStorage} from '../hooks'; import styles from './Components.css'; function Components(_: {||}) { - return - - - - {({resizeElementRef, onResizeStart, resizeElementStyles}) => - -
- -
-
+ return ( + + + + + {({resizeElementRef, onResizeStart, resizeElementStyles}) => ( +
-
-
- - }> - - - -
- - -
} -
-
-
-
; + ref={resizeElementRef} + className={styles.TreeWrapper} + style={{ + ...resizeElementStyles, + }}> + +
+
+
+
+
+ + }> + + + +
+ + + + )} + + + + + ); } const resizeDirections = { @@ -74,10 +73,12 @@ const resizeDirections = { VERTICAL: 'VERTICAL', }; - -function ComponentResizer({ children }: {| children: React$Node |}) { +function ComponentResizer({children}): {|children: Function|} { const [isResizing, setIsResizing] = useState(false); - const [horizontalPercentage, setHorizontalPercentage] = useLocalStorage( + const [ + horizontalPercentage, + setHorizontalPercentage, + ] = useLocalStorage( `React::DevTools::resizedElementPercentage::${resizeDirections.HORIZONTAL}`, 65, ); @@ -89,9 +90,15 @@ function ComponentResizer({ children }: {| children: React$Node |}) { const componentsWrapperRef = useRef(null); const resizeElementRef = useRef(null); - const resizeElementStyles = useMemo(() => ({ - flexBasis: `${window.innerWidth > 600 ? horizontalPercentage : verticalPercentage}%`, - }), [horizontalPercentage, verticalPercentage]); + + const resizeElementStyles = useMemo( + () => ({ + flexBasis: `${ + window.innerWidth > 600 ? horizontalPercentage : verticalPercentage + }%`, + }), + [horizontalPercentage, verticalPercentage], + ); const onResizeStart = useCallback(() => { setIsResizing(true); @@ -101,51 +108,77 @@ function ComponentResizer({ children }: {| children: React$Node |}) { setIsResizing(false); }, [setIsResizing]); - const onResize = useCallback((e) => { - if (!isResizing || (componentsWrapperRef.current === null || resizeElementRef.current === null)) { - return; - } - - e.preventDefault(); - - const {height, width, left, top} = componentsWrapperRef.current.getBoundingClientRect(); - const resizeDirection = width > 600 ? resizeDirections.HORIZONTAL : resizeDirections.VERTICAL; - const currentMousePosition = resizeDirection === resizeDirections.HORIZONTAL ? (e.clientX - left) : (e.clientY - top); - const boundary = { - min: 40, - max: (resizeDirection === resizeDirections.HORIZONTAL ? width - 40 : height - 40), - }; - const mousePositionInBounds = currentMousePosition > boundary.min && currentMousePosition < boundary.max; - - if (mousePositionInBounds) { - const updatedFlexBasisValue = (currentMousePosition / (resizeDirection === resizeDirections.HORIZONTAL ? width : height)) * 100; - - resizeElementRef.current.style.flexBasis = `${updatedFlexBasisValue}%`; + const onResize = useCallback( + e => { + if ( + !isResizing || + componentsWrapperRef.current === null || + resizeElementRef.current === null + ) { + return; + } - clearTimeout(updateLocalStorageTimeoutId.current); - updateLocalStorageTimeoutId.current = setTimeout(() => { - resizeDirection === resizeDirections.HORIZONTAL ? setHorizontalPercentage(updatedFlexBasisValue) : setVerticalPercentage(updatedFlexBasisValue); - }, 500); - } - }, [componentsWrapperRef, resizeElementRef, isResizing]); + e.preventDefault(); + + const { + height, + width, + left, + top, + } = componentsWrapperRef.current.getBoundingClientRect(); + const resizeDirection = + width > 600 ? resizeDirections.HORIZONTAL : resizeDirections.VERTICAL; + const currentMousePosition = + resizeDirection === resizeDirections.HORIZONTAL + ? e.clientX - left + : e.clientY - top; + const boundary = { + min: 40, + max: + resizeDirection === resizeDirections.HORIZONTAL + ? width - 40 + : height - 40, + }; + const mousePositionInBounds = + currentMousePosition > boundary.min && + currentMousePosition < boundary.max; + + if (mousePositionInBounds) { + const updatedFlexBasisValue = + (currentMousePosition / + (resizeDirection === resizeDirections.HORIZONTAL + ? width + : height)) * + 100; + + resizeElementRef.current.style.flexBasis = `${updatedFlexBasisValue}%`; + + clearTimeout(updateLocalStorageTimeoutId.current); + + updateLocalStorageTimeoutId.current = setTimeout(() => { + if (resizeDirection === resizeDirections.HORIZONTAL) { + setHorizontalPercentage(updatedFlexBasisValue); + } else { + setVerticalPercentage(updatedFlexBasisValue); + } + }, 500); + } + }, + [componentsWrapperRef, resizeElementRef, isResizing], + ); return (
+ {...(isResizing && { + onMouseMove: onResize, + onMouseLeave: onResizeEnd, + onMouseUp: onResizeEnd, + })}> {children({resizeElementRef, onResizeStart, resizeElementStyles})}
- ) + ); } function Loading() { From 16dcd67d700af4d03f0b28130db98e54fd0074db Mon Sep 17 00:00:00 2001 From: Hristo Kanchev Date: Sat, 15 Feb 2020 09:46:27 +0100 Subject: [PATCH 03/17] feat: DevTools - Added debug comments. --- .../src/devtools/views/Components/Components.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Components.js b/packages/react-devtools-shared/src/devtools/views/Components/Components.js index 77b57928c2c..4a3697f552a 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Components.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/Components.js @@ -90,7 +90,9 @@ function ComponentResizer({children}): {|children: Function|} { const componentsWrapperRef = useRef(null); const resizeElementRef = useRef(null); - + // TODO: We might be saving the localStorage values, + // TODO: but window.innerWidth might be bellow 600 so that why it's broken. + // TODO: OR we can't access the property when building the extension. :( const resizeElementStyles = useMemo( () => ({ flexBasis: `${ From 1c6add24a6f1a3901372ab099c6544402efe01d6 Mon Sep 17 00:00:00 2001 From: Hristo Kanchev Date: Sun, 16 Feb 2020 11:14:44 +0100 Subject: [PATCH 04/17] feat: DevTools - Removed Use Memo. --- .../devtools/views/Components/Components.js | 68 +++++++++++-------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Components.js b/packages/react-devtools-shared/src/devtools/views/Components/Components.js index 4a3697f552a..86755c3b022 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Components.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/Components.js @@ -12,7 +12,7 @@ import React, { Fragment, useRef, useState, - useMemo, + useLayoutEffect, useCallback, } from 'react'; import Tree from './Tree'; @@ -68,39 +68,30 @@ function Components(_: {||}) { ); } -const resizeDirections = { +const RESIZE_DIRECTIONS = { HORIZONTAL: 'HORIZONTAL', VERTICAL: 'VERTICAL', }; +const LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_HORIZONTAL_KEY = `React::DevTools::resizedElementPercentage::${RESIZE_DIRECTIONS.HORIZONTAL}`; +const LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_VERTICAL_KEY = `React::DevTools::resizedElementPercentage::${RESIZE_DIRECTIONS.VERTICAL}`; function ComponentResizer({children}): {|children: Function|} { - const [isResizing, setIsResizing] = useState(false); + const [isResizing, setIsResizing] = useState(false); const [ horizontalPercentage, setHorizontalPercentage, ] = useLocalStorage( - `React::DevTools::resizedElementPercentage::${resizeDirections.HORIZONTAL}`, + LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_HORIZONTAL_KEY, 65, ); const [verticalPercentage, setVerticalPercentage] = useLocalStorage( - `React::DevTools::resizedElementPercentage::${resizeDirections.VERTICAL}`, + LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_VERTICAL_KEY, 50, ); - const updateLocalStorageTimeoutId = useRef(null); - const componentsWrapperRef = useRef(null); - const resizeElementRef = useRef(null); - - // TODO: We might be saving the localStorage values, - // TODO: but window.innerWidth might be bellow 600 so that why it's broken. - // TODO: OR we can't access the property when building the extension. :( - const resizeElementStyles = useMemo( - () => ({ - flexBasis: `${ - window.innerWidth > 600 ? horizontalPercentage : verticalPercentage - }%`, - }), - [horizontalPercentage, verticalPercentage], - ); + const updateLocalStorageTimeoutId = useRef(null); + const componentsWrapperRef = useRef(null); + const resizeElementRef = useRef(null); + const [resizeElementStyles, setResizeElementStyles] = useState({}); const onResizeStart = useCallback(() => { setIsResizing(true); @@ -115,7 +106,7 @@ function ComponentResizer({children}): {|children: Function|} { if ( !isResizing || componentsWrapperRef.current === null || - resizeElementRef.current === null + resizeElementRef.current === null ) { return; } @@ -129,26 +120,29 @@ function ComponentResizer({children}): {|children: Function|} { top, } = componentsWrapperRef.current.getBoundingClientRect(); const resizeDirection = - width > 600 ? resizeDirections.HORIZONTAL : resizeDirections.VERTICAL; - const currentMousePosition = - resizeDirection === resizeDirections.HORIZONTAL + width > 600 ? RESIZE_DIRECTIONS.HORIZONTAL : RESIZE_DIRECTIONS.VERTICAL; + const currentMousePosition: number = + resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL ? e.clientX - left : e.clientY - top; - const boundary = { + const boundary: {| + min: number, + max: number, + |} = { min: 40, max: - resizeDirection === resizeDirections.HORIZONTAL + resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL ? width - 40 : height - 40, }; - const mousePositionInBounds = + const mousePositionInBounds: boolean = currentMousePosition > boundary.min && currentMousePosition < boundary.max; if (mousePositionInBounds) { - const updatedFlexBasisValue = + const updatedFlexBasisValue: number = (currentMousePosition / - (resizeDirection === resizeDirections.HORIZONTAL + (resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL ? width : height)) * 100; @@ -158,7 +152,7 @@ function ComponentResizer({children}): {|children: Function|} { clearTimeout(updateLocalStorageTimeoutId.current); updateLocalStorageTimeoutId.current = setTimeout(() => { - if (resizeDirection === resizeDirections.HORIZONTAL) { + if (resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL) { setHorizontalPercentage(updatedFlexBasisValue); } else { setVerticalPercentage(updatedFlexBasisValue); @@ -169,6 +163,20 @@ function ComponentResizer({children}): {|children: Function|} { [componentsWrapperRef, resizeElementRef, isResizing], ); + useLayoutEffect(() => { + if (componentsWrapperRef.current !== null) { + if (componentsWrapperRef.current.getBoundingClientRect().width > 600) { + setResizeElementStyles({ + flexBasis: `${horizontalPercentage}%`, + }); + } else { + setResizeElementStyles({ + flexBasis: `${verticalPercentage}%`, + }); + } + } + }, [componentsWrapperRef, horizontalPercentage, verticalPercentage]); + return (
Date: Sun, 16 Feb 2020 11:34:51 +0100 Subject: [PATCH 05/17] feat: DevTools - Added types. --- .../devtools/views/Components/Components.js | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Components.js b/packages/react-devtools-shared/src/devtools/views/Components/Components.js index 86755c3b022..b7160346d9e 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Components.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/Components.js @@ -68,10 +68,17 @@ function Components(_: {||}) { ); } -const RESIZE_DIRECTIONS = { +type HorizontalResizeDirection = 'HORIZONTAL'; +type VerticalResizeDirection = 'VERTICAL'; + +const RESIZE_DIRECTIONS: {| + HORIZONTAL: HorizontalResizeDirection, + VERTICAL: VerticalResizeDirection, +|} = { HORIZONTAL: 'HORIZONTAL', VERTICAL: 'VERTICAL', }; + const LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_HORIZONTAL_KEY = `React::DevTools::resizedElementPercentage::${RESIZE_DIRECTIONS.HORIZONTAL}`; const LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_VERTICAL_KEY = `React::DevTools::resizedElementPercentage::${RESIZE_DIRECTIONS.VERTICAL}`; @@ -92,6 +99,16 @@ function ComponentResizer({children}): {|children: Function|} { const componentsWrapperRef = useRef(null); const resizeElementRef = useRef(null); const [resizeElementStyles, setResizeElementStyles] = useState({}); + const getResizeDirection: Function = useCallback(() => { + if (componentsWrapperRef.current === null) { + return RESIZE_DIRECTIONS.HORIZONTAL; + } + const {width} = componentsWrapperRef.current.getBoundingClientRect(); + + return width > 600 + ? RESIZE_DIRECTIONS.HORIZONTAL + : RESIZE_DIRECTIONS.VERTICAL; + }, [componentsWrapperRef]); const onResizeStart = useCallback(() => { setIsResizing(true); @@ -119,8 +136,7 @@ function ComponentResizer({children}): {|children: Function|} { left, top, } = componentsWrapperRef.current.getBoundingClientRect(); - const resizeDirection = - width > 600 ? RESIZE_DIRECTIONS.HORIZONTAL : RESIZE_DIRECTIONS.VERTICAL; + const resizeDirection = getResizeDirection(); const currentMousePosition: number = resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL ? e.clientX - left @@ -165,7 +181,7 @@ function ComponentResizer({children}): {|children: Function|} { useLayoutEffect(() => { if (componentsWrapperRef.current !== null) { - if (componentsWrapperRef.current.getBoundingClientRect().width > 600) { + if (getResizeDirection() === RESIZE_DIRECTIONS.HORIZONTAL) { setResizeElementStyles({ flexBasis: `${horizontalPercentage}%`, }); From 02367548294bfbf6dc04efcab7aa1180ed4b833d Mon Sep 17 00:00:00 2001 From: Hristo Kanchev Date: Mon, 17 Feb 2020 15:00:27 +0100 Subject: [PATCH 06/17] feat: DevTools - Extracted values to constants. --- .../devtools/views/Components/Components.js | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Components.js b/packages/react-devtools-shared/src/devtools/views/Components/Components.js index b7160346d9e..a6031a01ebc 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Components.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/Components.js @@ -103,9 +103,10 @@ function ComponentResizer({children}): {|children: Function|} { if (componentsWrapperRef.current === null) { return RESIZE_DIRECTIONS.HORIZONTAL; } + const VERTICAL_MODE_MAX_WIDTH: number = 600; const {width} = componentsWrapperRef.current.getBoundingClientRect(); - return width > 600 + return width > VERTICAL_MODE_MAX_WIDTH ? RESIZE_DIRECTIONS.HORIZONTAL : RESIZE_DIRECTIONS.VERTICAL; }, [componentsWrapperRef]); @@ -141,27 +142,26 @@ function ComponentResizer({children}): {|children: Function|} { resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL ? e.clientX - left : e.clientY - top; + const BOUNDARY_PADDING: number = 40; const boundary: {| min: number, max: number, |} = { - min: 40, + min: BOUNDARY_PADDING, max: resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL - ? width - 40 - : height - 40, + ? width - BOUNDARY_PADDING + : height - BOUNDARY_PADDING, }; - const mousePositionInBounds: boolean = + const isMousePositionInBounds: boolean = currentMousePosition > boundary.min && currentMousePosition < boundary.max; - if (mousePositionInBounds) { + if (isMousePositionInBounds) { + const resizedElementDimension: number = + resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL ? width : height; const updatedFlexBasisValue: number = - (currentMousePosition / - (resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL - ? width - : height)) * - 100; + (currentMousePosition / resizedElementDimension) * 100; resizeElementRef.current.style.flexBasis = `${updatedFlexBasisValue}%`; From 1f2e54a2ed721e0e2a0856cd26a51ff614bbf6a6 Mon Sep 17 00:00:00 2001 From: Hristo Kanchev Date: Wed, 19 Feb 2020 09:51:30 +0100 Subject: [PATCH 07/17] feat: DevTools - Removed useCallback. --- .../devtools/views/Components/Components.js | 121 ++++++++---------- 1 file changed, 56 insertions(+), 65 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Components.js b/packages/react-devtools-shared/src/devtools/views/Components/Components.js index a6031a01ebc..d5077df3875 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Components.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/Components.js @@ -111,73 +111,64 @@ function ComponentResizer({children}): {|children: Function|} { : RESIZE_DIRECTIONS.VERTICAL; }, [componentsWrapperRef]); - const onResizeStart = useCallback(() => { - setIsResizing(true); - }, [setIsResizing]); - - const onResizeEnd = useCallback(() => { - setIsResizing(false); - }, [setIsResizing]); - - const onResize = useCallback( - e => { - if ( - !isResizing || - componentsWrapperRef.current === null || - resizeElementRef.current === null - ) { - return; - } - - e.preventDefault(); + const onResizeStart = () => setIsResizing(true); + const onResizeEnd = () => setIsResizing(false); + const onResize = e => { + if ( + !isResizing || + componentsWrapperRef.current === null || + resizeElementRef.current === null + ) { + return; + } - const { - height, - width, - left, - top, - } = componentsWrapperRef.current.getBoundingClientRect(); - const resizeDirection = getResizeDirection(); - const currentMousePosition: number = + e.preventDefault(); + + const { + height, + width, + left, + top, + } = componentsWrapperRef.current.getBoundingClientRect(); + const resizeDirection = getResizeDirection(); + const currentMousePosition: number = + resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL + ? e.clientX - left + : e.clientY - top; + const BOUNDARY_PADDING: number = 40; + const boundary: {| + min: number, + max: number, + |} = { + min: BOUNDARY_PADDING, + max: resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL - ? e.clientX - left - : e.clientY - top; - const BOUNDARY_PADDING: number = 40; - const boundary: {| - min: number, - max: number, - |} = { - min: BOUNDARY_PADDING, - max: - resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL - ? width - BOUNDARY_PADDING - : height - BOUNDARY_PADDING, - }; - const isMousePositionInBounds: boolean = - currentMousePosition > boundary.min && - currentMousePosition < boundary.max; - - if (isMousePositionInBounds) { - const resizedElementDimension: number = - resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL ? width : height; - const updatedFlexBasisValue: number = - (currentMousePosition / resizedElementDimension) * 100; - - resizeElementRef.current.style.flexBasis = `${updatedFlexBasisValue}%`; - - clearTimeout(updateLocalStorageTimeoutId.current); - - updateLocalStorageTimeoutId.current = setTimeout(() => { - if (resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL) { - setHorizontalPercentage(updatedFlexBasisValue); - } else { - setVerticalPercentage(updatedFlexBasisValue); - } - }, 500); - } - }, - [componentsWrapperRef, resizeElementRef, isResizing], - ); + ? width - BOUNDARY_PADDING + : height - BOUNDARY_PADDING, + }; + const isMousePositionInBounds: boolean = + currentMousePosition > boundary.min && + currentMousePosition < boundary.max; + + if (isMousePositionInBounds) { + const resizedElementDimension: number = + resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL ? width : height; + const updatedFlexBasisValue: number = + (currentMousePosition / resizedElementDimension) * 100; + + resizeElementRef.current.style.flexBasis = `${updatedFlexBasisValue}%`; + + clearTimeout(updateLocalStorageTimeoutId.current); + + updateLocalStorageTimeoutId.current = setTimeout(() => { + if (resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL) { + setHorizontalPercentage(updatedFlexBasisValue); + } else { + setVerticalPercentage(updatedFlexBasisValue); + } + }, 500); + } + }; useLayoutEffect(() => { if (componentsWrapperRef.current !== null) { From 9cee4ef82ce94d410a62cc3b3820a062c394e82b Mon Sep 17 00:00:00 2001 From: Hristo Kanchev Date: Sun, 23 Feb 2020 10:24:54 +0100 Subject: [PATCH 08/17] feat: DevTools - Finished refactoring. --- .../devtools/views/Components/Components.css | 2 +- .../devtools/views/Components/Components.js | 180 +++++++++++------- 2 files changed, 117 insertions(+), 65 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Components.css b/packages/react-devtools-shared/src/devtools/views/Components/Components.css index b1dacee87c2..a8e444a786d 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Components.css +++ b/packages/react-devtools-shared/src/devtools/views/Components/Components.css @@ -43,7 +43,7 @@ } .SelectedElementWrapper { - flex: 0 0 50%; + flex: 1 1 50%; } .ResizeBar { diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Components.js b/packages/react-devtools-shared/src/devtools/views/Components/Components.js index d5077df3875..6fbdb1c61d7 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Components.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/Components.js @@ -7,14 +7,7 @@ * @flow */ -import React, { - Suspense, - Fragment, - useRef, - useState, - useLayoutEffect, - useCallback, -} from 'react'; +import React, {Suspense, Fragment, useRef, useEffect, useReducer} from 'react'; import Tree from './Tree'; import SelectedElement from './SelectedElement'; import {InspectedElementContextController} from './InspectedElementContext'; @@ -79,44 +72,113 @@ const RESIZE_DIRECTIONS: {| VERTICAL: 'VERTICAL', }; -const LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_HORIZONTAL_KEY = `React::DevTools::resizedElementPercentage::${RESIZE_DIRECTIONS.HORIZONTAL}`; -const LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_VERTICAL_KEY = `React::DevTools::resizedElementPercentage::${RESIZE_DIRECTIONS.VERTICAL}`; - -function ComponentResizer({children}): {|children: Function|} { - const [isResizing, setIsResizing] = useState(false); +function createResizeReducer(wrapperRef) { + const LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_HORIZONTAL_KEY = `React::DevTools::resizedElementPercentage::${RESIZE_DIRECTIONS.HORIZONTAL}`; + const LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_VERTICAL_KEY = `React::DevTools::resizedElementPercentage::${RESIZE_DIRECTIONS.VERTICAL}`; const [ horizontalPercentage, setHorizontalPercentage, - ] = useLocalStorage( + ] = useLocalStorage( LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_HORIZONTAL_KEY, - 65, + '65%', ); - const [verticalPercentage, setVerticalPercentage] = useLocalStorage( + const [verticalPercentage, setVerticalPercentage] = useLocalStorage( LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_VERTICAL_KEY, - 50, + '50%', ); - const updateLocalStorageTimeoutId = useRef(null); - const componentsWrapperRef = useRef(null); - const resizeElementRef = useRef(null); - const [resizeElementStyles, setResizeElementStyles] = useState({}); - const getResizeDirection: Function = useCallback(() => { - if (componentsWrapperRef.current === null) { - return RESIZE_DIRECTIONS.HORIZONTAL; + const resizeTimeout = useRef(null); + + const getResizeDirection: Function = ref => () => { + if (ref.current != null) { + const VERTICAL_MODE_MAX_WIDTH: number = 600; + const {width} = ref.current.getBoundingClientRect(); + + return width > VERTICAL_MODE_MAX_WIDTH + ? RESIZE_DIRECTIONS.HORIZONTAL + : RESIZE_DIRECTIONS.VERTICAL; + } + + return RESIZE_DIRECTIONS.HORIZONTAL; + }; + + // We need to watch/set for changes to this ref in order to get the correct resize direction. + useEffect(() => { + if (wrapperRef.current != null) { + dispatch({type: 'setWrapperRef', payload: wrapperRef}); + } + }, [wrapperRef]); + + const initialState = { + wrapperRef: wrapperRef, + isResizing: false, + horizontalPercentage, + verticalPercentage, + getResizeDirection: getResizeDirection(wrapperRef), + }; + + const ACTION_TYPES = { + SET_IS_RESIZING: 'setIsResizing', + SET_WRAPPER_REF: 'setWrapperRef', + SET_HORIZONTAL_PERCENTAGE: 'setHorizontalPercentage', + SET_VERTICAL_PERCENTAGE: 'setVerticalPercentage', + }; + + // eslint-disable-next-line no-shadow + const [state, dispatch] = useReducer((state, action) => { + switch (action.type) { + case ACTION_TYPES.SET_IS_RESIZING: + return { + ...state, + isResizing: action.payload, + }; + case ACTION_TYPES.SET_WRAPPER_REF: + return { + ...state, + wrapperRef: action.payload, + getResizeDirection: getResizeDirection(action.payload), + }; + case ACTION_TYPES.SET_HORIZONTAL_PERCENTAGE: + case ACTION_TYPES.SET_VERTICAL_PERCENTAGE: + const percentageState = { + [action.type === ACTION_TYPES.SET_HORIZONTAL_PERCENTAGE + ? 'horizontalPercentage' + : 'verticalPercentage']: action.payload, + }; + + clearTimeout(resizeTimeout.current); + resizeTimeout.current = setTimeout(() => { + if (action.type === ACTION_TYPES.SET_HORIZONTAL_PERCENTAGE) { + setHorizontalPercentage(action.payload); + } else { + setVerticalPercentage(action.payload); + } + }, 400); + + return { + ...state, + ...percentageState, + }; + default: + return state; } - const VERTICAL_MODE_MAX_WIDTH: number = 600; - const {width} = componentsWrapperRef.current.getBoundingClientRect(); + }, initialState); - return width > VERTICAL_MODE_MAX_WIDTH - ? RESIZE_DIRECTIONS.HORIZONTAL - : RESIZE_DIRECTIONS.VERTICAL; - }, [componentsWrapperRef]); + return [state, dispatch, ACTION_TYPES]; +} - const onResizeStart = () => setIsResizing(true); - const onResizeEnd = () => setIsResizing(false); +function ComponentResizer({children}): {|children: Function|} { + const componentsWrapperRef = useRef(null); + const resizeElementRef = useRef(null); + const [state, dispatch, ACTION_TYPES] = createResizeReducer(componentsWrapperRef); + + const onResizeStart = () => + dispatch({type: ACTION_TYPES.SET_IS_RESIZING, payload: true}); + const onResizeEnd = () => + dispatch({type: ACTION_TYPES.SET_IS_RESIZING, payload: false}); const onResize = e => { if ( - !isResizing || - componentsWrapperRef.current === null || + !state.isResizing || + state.wrapperRef.current === null || resizeElementRef.current === null ) { return; @@ -129,13 +191,14 @@ function ComponentResizer({children}): {|children: Function|} { width, left, top, - } = componentsWrapperRef.current.getBoundingClientRect(); - const resizeDirection = getResizeDirection(); + } = state.wrapperRef.current.getBoundingClientRect(); + const resizeDirection = state.getResizeDirection(); + const currentMousePosition: number = resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL ? e.clientX - left : e.clientY - top; - const BOUNDARY_PADDING: number = 40; + const BOUNDARY_PADDING: number = 42; const boundary: {| min: number, max: number, @@ -153,42 +216,31 @@ function ComponentResizer({children}): {|children: Function|} { if (isMousePositionInBounds) { const resizedElementDimension: number = resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL ? width : height; - const updatedFlexBasisValue: number = - (currentMousePosition / resizedElementDimension) * 100; - - resizeElementRef.current.style.flexBasis = `${updatedFlexBasisValue}%`; - - clearTimeout(updateLocalStorageTimeoutId.current); + const updatedFlexBasisValue: string = `${(currentMousePosition / + resizedElementDimension) * + 100}%`; + const SET_PERCENTAGE_ACTION = + resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL + ? ACTION_TYPES.SET_HORIZONTAL_PERCENTAGE + : ACTION_TYPES.SET_VERTICAL_PERCENTAGE; - updateLocalStorageTimeoutId.current = setTimeout(() => { - if (resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL) { - setHorizontalPercentage(updatedFlexBasisValue); - } else { - setVerticalPercentage(updatedFlexBasisValue); - } - }, 500); + resizeElementRef.current.style.flexBasis = updatedFlexBasisValue; + dispatch({type: SET_PERCENTAGE_ACTION, payload: updatedFlexBasisValue}); } }; - useLayoutEffect(() => { - if (componentsWrapperRef.current !== null) { - if (getResizeDirection() === RESIZE_DIRECTIONS.HORIZONTAL) { - setResizeElementStyles({ - flexBasis: `${horizontalPercentage}%`, - }); - } else { - setResizeElementStyles({ - flexBasis: `${verticalPercentage}%`, - }); - } - } - }, [componentsWrapperRef, horizontalPercentage, verticalPercentage]); + const resizeElementStyles = { + flexBasis: + state.getResizeDirection() === RESIZE_DIRECTIONS.HORIZONTAL + ? state.horizontalPercentage + : state.verticalPercentage, + }; return (
Date: Sun, 23 Feb 2020 10:28:07 +0100 Subject: [PATCH 09/17] feat: DevTools - Merging fixup. --- .../src/devtools/views/Components/Components.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Components.js b/packages/react-devtools-shared/src/devtools/views/Components/Components.js index 6fbdb1c61d7..1dededc9f68 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Components.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/Components.js @@ -7,7 +7,8 @@ * @flow */ -import React, {Suspense, Fragment, useRef, useEffect, useReducer} from 'react'; +import * as React from 'react'; +import {Suspense, Fragment, useRef, useEffect, useReducer} from 'react'; import Tree from './Tree'; import SelectedElement from './SelectedElement'; import {InspectedElementContextController} from './InspectedElementContext'; From 0c2ad23eaec8eab311088215626a737384eba8f7 Mon Sep 17 00:00:00 2001 From: Hristo Kanchev Date: Sun, 23 Feb 2020 10:43:44 +0100 Subject: [PATCH 10/17] feat: DevTools - Prettier fix. --- .../src/devtools/views/Components/Components.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Components.js b/packages/react-devtools-shared/src/devtools/views/Components/Components.js index 1dededc9f68..c12a0aa7868 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Components.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/Components.js @@ -170,7 +170,9 @@ function createResizeReducer(wrapperRef) { function ComponentResizer({children}): {|children: Function|} { const componentsWrapperRef = useRef(null); const resizeElementRef = useRef(null); - const [state, dispatch, ACTION_TYPES] = createResizeReducer(componentsWrapperRef); + const [state, dispatch, ACTION_TYPES] = createResizeReducer( + componentsWrapperRef, + ); const onResizeStart = () => dispatch({type: ACTION_TYPES.SET_IS_RESIZING, payload: true}); From 3ba1909dbe8c78936f6001c7ad0df98ed670261c Mon Sep 17 00:00:00 2001 From: Hristo Kanchev Date: Mon, 24 Feb 2020 21:16:52 +0100 Subject: [PATCH 11/17] feat: DevTools - Extracted code from Components fil. --- .../devtools/views/Components/Components.css | 15 -- .../devtools/views/Components/Components.js | 205 +---------------- .../views/Components/ComponentsResizer.css | 16 ++ .../views/Components/ComponentsResizer.js | 207 ++++++++++++++++++ 4 files changed, 229 insertions(+), 214 deletions(-) create mode 100644 packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.css create mode 100644 packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Components.css b/packages/react-devtools-shared/src/devtools/views/Components/Components.css index a8e444a786d..00e2c35f82a 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Components.css +++ b/packages/react-devtools-shared/src/devtools/views/Components/Components.css @@ -1,14 +1,3 @@ -.ComponentsWrapper { - position: relative; - width: 100%; - height: 100%; - display: flex; - flex-direction: row; - background-color: var(--color-background); - color: var(--color-text); - font-family: var(--font-family-sans); -} - .TreeWrapper { flex: 0 0 65%; overflow: auto; @@ -34,10 +23,6 @@ } @media screen and (max-width: 600px) { - .ComponentsWrapper { - flex-direction: column; - } - .TreeWrapper { flex: 0 0 50%; } diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Components.js b/packages/react-devtools-shared/src/devtools/views/Components/Components.js index c12a0aa7868..c525a0c46a9 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Components.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/Components.js @@ -8,17 +8,17 @@ */ import * as React from 'react'; -import {Suspense, Fragment, useRef, useEffect, useReducer} from 'react'; +import {Suspense, Fragment } from 'react'; import Tree from './Tree'; import SelectedElement from './SelectedElement'; import {InspectedElementContextController} from './InspectedElementContext'; import {NativeStyleContextController} from './NativeStyleEditor/context'; import {OwnersListContextController} from './OwnersListContext'; +import ComponentsResizer from './ComponentsResizer'; import portaledContent from '../portaledContent'; import {ModalDialog} from '../ModalDialog'; import SettingsModal from 'react-devtools-shared/src/devtools/views/Settings/SettingsModal'; import {SettingsModalContextController} from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContext'; -import {useLocalStorage} from '../hooks'; import styles from './Components.css'; @@ -27,15 +27,13 @@ function Components(_: {||}) { - - {({resizeElementRef, onResizeStart, resizeElementStyles}) => ( + + {({resizeElementRef, onResizeStart}) => (
+ >
@@ -55,204 +53,13 @@ function Components(_: {||}) { )} - + ); } -type HorizontalResizeDirection = 'HORIZONTAL'; -type VerticalResizeDirection = 'VERTICAL'; - -const RESIZE_DIRECTIONS: {| - HORIZONTAL: HorizontalResizeDirection, - VERTICAL: VerticalResizeDirection, -|} = { - HORIZONTAL: 'HORIZONTAL', - VERTICAL: 'VERTICAL', -}; - -function createResizeReducer(wrapperRef) { - const LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_HORIZONTAL_KEY = `React::DevTools::resizedElementPercentage::${RESIZE_DIRECTIONS.HORIZONTAL}`; - const LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_VERTICAL_KEY = `React::DevTools::resizedElementPercentage::${RESIZE_DIRECTIONS.VERTICAL}`; - const [ - horizontalPercentage, - setHorizontalPercentage, - ] = useLocalStorage( - LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_HORIZONTAL_KEY, - '65%', - ); - const [verticalPercentage, setVerticalPercentage] = useLocalStorage( - LOCAL_STORAGE_RESIZE_ELEMENT_PERCENTAGE_VERTICAL_KEY, - '50%', - ); - const resizeTimeout = useRef(null); - - const getResizeDirection: Function = ref => () => { - if (ref.current != null) { - const VERTICAL_MODE_MAX_WIDTH: number = 600; - const {width} = ref.current.getBoundingClientRect(); - - return width > VERTICAL_MODE_MAX_WIDTH - ? RESIZE_DIRECTIONS.HORIZONTAL - : RESIZE_DIRECTIONS.VERTICAL; - } - - return RESIZE_DIRECTIONS.HORIZONTAL; - }; - - // We need to watch/set for changes to this ref in order to get the correct resize direction. - useEffect(() => { - if (wrapperRef.current != null) { - dispatch({type: 'setWrapperRef', payload: wrapperRef}); - } - }, [wrapperRef]); - - const initialState = { - wrapperRef: wrapperRef, - isResizing: false, - horizontalPercentage, - verticalPercentage, - getResizeDirection: getResizeDirection(wrapperRef), - }; - - const ACTION_TYPES = { - SET_IS_RESIZING: 'setIsResizing', - SET_WRAPPER_REF: 'setWrapperRef', - SET_HORIZONTAL_PERCENTAGE: 'setHorizontalPercentage', - SET_VERTICAL_PERCENTAGE: 'setVerticalPercentage', - }; - - // eslint-disable-next-line no-shadow - const [state, dispatch] = useReducer((state, action) => { - switch (action.type) { - case ACTION_TYPES.SET_IS_RESIZING: - return { - ...state, - isResizing: action.payload, - }; - case ACTION_TYPES.SET_WRAPPER_REF: - return { - ...state, - wrapperRef: action.payload, - getResizeDirection: getResizeDirection(action.payload), - }; - case ACTION_TYPES.SET_HORIZONTAL_PERCENTAGE: - case ACTION_TYPES.SET_VERTICAL_PERCENTAGE: - const percentageState = { - [action.type === ACTION_TYPES.SET_HORIZONTAL_PERCENTAGE - ? 'horizontalPercentage' - : 'verticalPercentage']: action.payload, - }; - - clearTimeout(resizeTimeout.current); - resizeTimeout.current = setTimeout(() => { - if (action.type === ACTION_TYPES.SET_HORIZONTAL_PERCENTAGE) { - setHorizontalPercentage(action.payload); - } else { - setVerticalPercentage(action.payload); - } - }, 400); - - return { - ...state, - ...percentageState, - }; - default: - return state; - } - }, initialState); - - return [state, dispatch, ACTION_TYPES]; -} - -function ComponentResizer({children}): {|children: Function|} { - const componentsWrapperRef = useRef(null); - const resizeElementRef = useRef(null); - const [state, dispatch, ACTION_TYPES] = createResizeReducer( - componentsWrapperRef, - ); - - const onResizeStart = () => - dispatch({type: ACTION_TYPES.SET_IS_RESIZING, payload: true}); - const onResizeEnd = () => - dispatch({type: ACTION_TYPES.SET_IS_RESIZING, payload: false}); - const onResize = e => { - if ( - !state.isResizing || - state.wrapperRef.current === null || - resizeElementRef.current === null - ) { - return; - } - - e.preventDefault(); - - const { - height, - width, - left, - top, - } = state.wrapperRef.current.getBoundingClientRect(); - const resizeDirection = state.getResizeDirection(); - - const currentMousePosition: number = - resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL - ? e.clientX - left - : e.clientY - top; - const BOUNDARY_PADDING: number = 42; - const boundary: {| - min: number, - max: number, - |} = { - min: BOUNDARY_PADDING, - max: - resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL - ? width - BOUNDARY_PADDING - : height - BOUNDARY_PADDING, - }; - const isMousePositionInBounds: boolean = - currentMousePosition > boundary.min && - currentMousePosition < boundary.max; - - if (isMousePositionInBounds) { - const resizedElementDimension: number = - resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL ? width : height; - const updatedFlexBasisValue: string = `${(currentMousePosition / - resizedElementDimension) * - 100}%`; - const SET_PERCENTAGE_ACTION = - resizeDirection === RESIZE_DIRECTIONS.HORIZONTAL - ? ACTION_TYPES.SET_HORIZONTAL_PERCENTAGE - : ACTION_TYPES.SET_VERTICAL_PERCENTAGE; - - resizeElementRef.current.style.flexBasis = updatedFlexBasisValue; - dispatch({type: SET_PERCENTAGE_ACTION, payload: updatedFlexBasisValue}); - } - }; - - const resizeElementStyles = { - flexBasis: - state.getResizeDirection() === RESIZE_DIRECTIONS.HORIZONTAL - ? state.horizontalPercentage - : state.verticalPercentage, - }; - - return ( -
- {children({resizeElementRef, onResizeStart, resizeElementStyles})} -
- ); -} - function Loading() { return
Loading...
; } diff --git a/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.css b/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.css new file mode 100644 index 00000000000..8a86aa1246a --- /dev/null +++ b/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.css @@ -0,0 +1,16 @@ +.ComponentsWrapper { + position: relative; + width: 100%; + height: 100%; + display: flex; + flex-direction: row; + background-color: var(--color-background); + color: var(--color-text); + font-family: var(--font-family-sans); +} + +@media screen and (max-width: 600px) { + .ComponentsWrapper { + flex-direction: column; + } +} diff --git a/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js b/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js new file mode 100644 index 00000000000..1dc2a233240 --- /dev/null +++ b/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js @@ -0,0 +1,207 @@ +import type {ElementRef} from 'react'; + +import * as React from 'react'; +import {useEffect, useLayoutEffect, useReducer, useRef} from 'react'; +import { + localStorageGetItem, + localStorageSetItem, +} from 'react-devtools-shared/src/storage'; +import styles from './ComponentsResizer.css'; + +const LOCAL_STORAGE_KEY = 'React::DevTools::createResizeReducer'; +const VERTICAL_MODE_MAX_WIDTH = 600; +const MINIMUM_SIZE = 50; + +type Props = {| + children: ({ + resizeElementRef: ElementRef, + onResizeStart: () => void, + }) => React$Node, +|}; + +export default function ComponentsResizer({children}: Props) { + const wrapperElementRef = useRef(null); + const resizeElementRef = useRef(null); + const [state, dispatch] = createResizeReducer( + wrapperElementRef, + resizeElementRef, + ); + + const {isResizing} = state; + + const onResizeStart = () => + dispatch({type: 'ACTION_SET_IS_RESIZING', payload: true}); + const onResizeEnd = () => + dispatch({type: 'ACTION_SET_IS_RESIZING', payload: false}); + + const onResize = event => { + const resizeElement = resizeElementRef.current; + const wrapperElement = wrapperElementRef.current; + + if (!isResizing || wrapperElement === null || resizeElement === null) { + return; + } + + event.preventDefault(); + + const orientation = getOrientation(wrapperElementRef); + + const {height, width, left, top} = wrapperElement.getBoundingClientRect(); + + const currentMousePosition = + orientation === 'horizontal' ? event.clientX - left : event.clientY - top; + + const boundaryMin = MINIMUM_SIZE; + const boundaryMax = + orientation === 'horizontal' + ? width - MINIMUM_SIZE + : height - MINIMUM_SIZE; + + const isMousePositionInBounds = + currentMousePosition > boundaryMin && currentMousePosition < boundaryMax; + + if (isMousePositionInBounds) { + const resizedElementDimension = + orientation === 'horizontal' ? width : height; + const actionType = + orientation === 'horizontal' + ? 'ACTION_SET_HORIZONTAL_PERCENTAGE' + : 'ACTION_SET_VERTICAL_PERCENTAGE'; + + resizeElement.style.flexBasis = `${(currentMousePosition / + resizedElementDimension) * + 100}%`; + + dispatch({ + type: actionType, + payload: currentMousePosition / resizedElementDimension, + }); + } + }; + + return ( +
+ {children({resizeElementRef, onResizeStart})} +
+ ); +} + +type Orientation = 'horizontal' | 'vertical'; + +type ResizeActionType = + | 'ACTION_SET_DID_MOUNT' + | 'ACTION_SET_IS_RESIZING' + | 'ACTION_SET_HORIZONTAL_PERCENTAGE' + | 'ACTION_SET_VERTICAL_PERCENTAGE'; + +type ResizeAction = {| + type: ResizeActionType, + payload: any, +|}; + +type ResizeState = {| + horizontalPercentage: number, + isResizing: boolean, + verticalPercentage: number, +|}; + +function initResizeState(): ResizeState { + let horizontalPercentage = 0.65; + let verticalPercentage = 0.5; + + try { + let data = localStorageGetItem(LOCAL_STORAGE_KEY); + if (data != null) { + data = JSON.parse(data); + horizontalPercentage = data.horizontalPercentage; + verticalPercentage = data.verticalPercentage; + } + } catch (error) {} + + return { + horizontalPercentage, + isResizing: false, + verticalPercentage, + }; +} + +function resizeReducer(state: ResizeState, action: ResizeAction): ResizeState { + switch (action.type) { + case 'ACTION_SET_IS_RESIZING': + return { + ...state, + isResizing: action.payload, + }; + case 'ACTION_SET_HORIZONTAL_PERCENTAGE': + return { + ...state, + horizontalPercentage: action.payload, + }; + case 'ACTION_SET_VERTICAL_PERCENTAGE': + return { + ...state, + verticalPercentage: action.payload, + }; + default: + return state; + } +} + +function getOrientation( + wrapperElementRef: ElementRef, +): null | Orientation { + const wrapperElement = wrapperElementRef.current; + if (wrapperElement != null) { + const {width} = wrapperElement.getBoundingClientRect(); + return width > VERTICAL_MODE_MAX_WIDTH ? 'horizontal' : 'vertical'; + } + return null; +} + +function createResizeReducer(wrapperElementRef, resizeElementRef) { + const [state, dispatch] = useReducer( + resizeReducer, + null, + initResizeState, + ); + const {horizontalPercentage, verticalPercentage} = state; + const orientationRef = useRef(null); + + useLayoutEffect(() => { + const orientation = getOrientation(wrapperElementRef); + + if (orientation !== orientationRef.current) { + orientationRef.current = orientation; + + const percentage = + orientation === 'horizontal' + ? horizontalPercentage + : verticalPercentage; + const resizeElement = resizeElementRef.current; + resizeElement.style.flexBasis = `${percentage * 100}%`; + } + }); + + useEffect(() => { + const timeoutID = setTimeout(() => { + localStorageSetItem( + LOCAL_STORAGE_KEY, + JSON.stringify({ + horizontalPercentage, + verticalPercentage, + }), + ); + }, 500); + + return () => clearTimeout(timeoutID); + }, [horizontalPercentage, verticalPercentage]); + + return [state, dispatch]; +} From 554f7e858589ab1af076ff446961776265a86723 Mon Sep 17 00:00:00 2001 From: Hristo Kanchev Date: Tue, 25 Feb 2020 10:35:00 +0100 Subject: [PATCH 12/17] feat: DevTools - Fixed orientation change issue. --- .../devtools/views/Components/Components.css | 4 ++-- .../devtools/views/Components/Components.js | 7 ++---- .../views/Components/ComponentsResizer.js | 24 ++++++++++--------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Components.css b/packages/react-devtools-shared/src/devtools/views/Components/Components.css index 00e2c35f82a..5db5eaea2d6 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Components.css +++ b/packages/react-devtools-shared/src/devtools/views/Components/Components.css @@ -1,5 +1,5 @@ .TreeWrapper { - flex: 0 0 65%; + flex: 0 0 var(--horizontal-resize-percentage); overflow: auto; } @@ -24,7 +24,7 @@ @media screen and (max-width: 600px) { .TreeWrapper { - flex: 0 0 50%; + flex: 0 0 var(--vertical-resize-percentage); } .SelectedElementWrapper { diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Components.js b/packages/react-devtools-shared/src/devtools/views/Components/Components.js index c525a0c46a9..af1cf3ac95f 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Components.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/Components.js @@ -8,7 +8,7 @@ */ import * as React from 'react'; -import {Suspense, Fragment } from 'react'; +import {Suspense, Fragment} from 'react'; import Tree from './Tree'; import SelectedElement from './SelectedElement'; import {InspectedElementContextController} from './InspectedElementContext'; @@ -30,10 +30,7 @@ function Components(_: {||}) { {({resizeElementRef, onResizeStart}) => ( -
+
diff --git a/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js b/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js index 1dc2a233240..7a7e46efcaf 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js @@ -20,8 +20,8 @@ type Props = {| |}; export default function ComponentsResizer({children}: Props) { - const wrapperElementRef = useRef(null); - const resizeElementRef = useRef(null); + const wrapperElementRef = useRef(null); + const resizeElementRef = useRef(null); const [state, dispatch] = createResizeReducer( wrapperElementRef, resizeElementRef, @@ -67,10 +67,12 @@ export default function ComponentsResizer({children}: Props) { orientation === 'horizontal' ? 'ACTION_SET_HORIZONTAL_PERCENTAGE' : 'ACTION_SET_VERTICAL_PERCENTAGE'; + const percentage = (currentMousePosition / resizedElementDimension) * 100; - resizeElement.style.flexBasis = `${(currentMousePosition / - resizedElementDimension) * - 100}%`; + resizeElement.style.setProperty( + `--${orientation}-resize-percentage`, + `${percentage}%`, + ); dispatch({ type: actionType, @@ -166,11 +168,7 @@ function getOrientation( } function createResizeReducer(wrapperElementRef, resizeElementRef) { - const [state, dispatch] = useReducer( - resizeReducer, - null, - initResizeState, - ); + const [state, dispatch] = useReducer(resizeReducer, null, initResizeState); const {horizontalPercentage, verticalPercentage} = state; const orientationRef = useRef(null); @@ -185,7 +183,11 @@ function createResizeReducer(wrapperElementRef, resizeElementRef) { ? horizontalPercentage : verticalPercentage; const resizeElement = resizeElementRef.current; - resizeElement.style.flexBasis = `${percentage * 100}%`; + + resizeElement.style.setProperty( + `--${orientation}-resize-percentage`, + `${percentage * 100}%`, + ); } }); From c243f4036980f087fc032f9a3865ee85fa4bdccf Mon Sep 17 00:00:00 2001 From: Hristo Kanchev Date: Tue, 25 Feb 2020 19:59:22 +0100 Subject: [PATCH 13/17] feat: DevTools - Added flow types for reducer and refs. --- .../views/Components/ComponentsResizer.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js b/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js index 7a7e46efcaf..7c03d5dbd75 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js @@ -1,3 +1,12 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + import type {ElementRef} from 'react'; import * as React from 'react'; @@ -20,8 +29,8 @@ type Props = {| |}; export default function ComponentsResizer({children}: Props) { - const wrapperElementRef = useRef(null); - const resizeElementRef = useRef(null); + const wrapperElementRef = useRef(null); + const resizeElementRef = useRef(null); const [state, dispatch] = createResizeReducer( wrapperElementRef, resizeElementRef, @@ -168,7 +177,7 @@ function getOrientation( } function createResizeReducer(wrapperElementRef, resizeElementRef) { - const [state, dispatch] = useReducer(resizeReducer, null, initResizeState); + const [state, dispatch] = useReducer(resizeReducer, null, initResizeState); const {horizontalPercentage, verticalPercentage} = state; const orientationRef = useRef(null); From 7f4dbd92924e2040c3dfd343081a6068b3887982 Mon Sep 17 00:00:00 2001 From: Hristo Kanchev Date: Tue, 25 Feb 2020 22:27:22 +0100 Subject: [PATCH 14/17] feat: DevTools - Fixed orientation change on initial load. --- .../views/Components/ComponentsResizer.js | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js b/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js index 7c03d5dbd75..2b1bfb2b284 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js @@ -78,10 +78,7 @@ export default function ComponentsResizer({children}: Props) { : 'ACTION_SET_VERTICAL_PERCENTAGE'; const percentage = (currentMousePosition / resizedElementDimension) * 100; - resizeElement.style.setProperty( - `--${orientation}-resize-percentage`, - `${percentage}%`, - ); + setResizeCSSVariable(resizeElementRef, orientation, percentage); dispatch({ type: actionType, @@ -176,11 +173,46 @@ function getOrientation( return null; } +function setResizeCSSVariable( + resizeElementRef: ElementRef, + orientation: null | Orientation, + percentage: number, +): void { + const resizeElement = resizeElementRef.current; + + if (resizeElement !== null && orientation !== null) { + resizeElement.style.setProperty( + `--${orientation}-resize-percentage`, + `${percentage}%`, + ); + } +} + function createResizeReducer(wrapperElementRef, resizeElementRef) { - const [state, dispatch] = useReducer(resizeReducer, null, initResizeState); + const [state, dispatch] = useReducer( + resizeReducer, + null, + initResizeState, + ); const {horizontalPercentage, verticalPercentage} = state; const orientationRef = useRef(null); + // Initial set up for the resize percentage CSS variables. + useLayoutEffect(() => { + const orientationAndPercentage = { + horizontal: horizontalPercentage, + vertical: verticalPercentage, + }; + + Object.keys(orientationAndPercentage).forEach(orientation => { + setResizeCSSVariable( + resizeElementRef, + orientation, + orientationAndPercentage[orientation] * 100, + ); + }); + }, []); + useLayoutEffect(() => { const orientation = getOrientation(wrapperElementRef); @@ -191,12 +223,8 @@ function createResizeReducer(wrapperElementRef, resizeElementRef) { orientation === 'horizontal' ? horizontalPercentage : verticalPercentage; - const resizeElement = resizeElementRef.current; - resizeElement.style.setProperty( - `--${orientation}-resize-percentage`, - `${percentage * 100}%`, - ); + setResizeCSSVariable(resizeElementRef, orientation, percentage * 100); } }); From c773be315cb921905dadedf89251b9f8faba9146 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Wed, 26 Feb 2020 11:04:01 -0800 Subject: [PATCH 15/17] Update packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js --- .../views/Components/ComponentsResizer.js | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js b/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js index 2b1bfb2b284..1696eee01be 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js @@ -214,19 +214,17 @@ function createResizeReducer(wrapperElementRef, resizeElementRef) { }, []); useLayoutEffect(() => { - const orientation = getOrientation(wrapperElementRef); - - if (orientation !== orientationRef.current) { - orientationRef.current = orientation; - - const percentage = - orientation === 'horizontal' - ? horizontalPercentage - : verticalPercentage; - - setResizeCSSVariable(resizeElementRef, orientation, percentage * 100); - } - }); + setResizeCSSVariable( + resizeElementRef, + 'horizontal', + horizontalPercentage * 100, + ); + setResizeCSSVariable( + resizeElementRef, + 'vertical', + verticalPercentage * 100, + ); + }, []); useEffect(() => { const timeoutID = setTimeout(() => { From 27f59066bdc5cf980eeeb2806095d0516c501547 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Wed, 26 Feb 2020 11:06:28 -0800 Subject: [PATCH 16/17] Removed unused `orientationRef` --- .../src/devtools/views/Components/ComponentsResizer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js b/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js index 1696eee01be..de339f6a2dd 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js @@ -195,7 +195,6 @@ function createResizeReducer(wrapperElementRef, resizeElementRef) { initResizeState, ); const {horizontalPercentage, verticalPercentage} = state; - const orientationRef = useRef(null); // Initial set up for the resize percentage CSS variables. useLayoutEffect(() => { From 267f242a6eee84e6386c37726b65f20df86caab4 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Wed, 26 Feb 2020 11:17:22 -0800 Subject: [PATCH 17/17] Fix Flow ref issue --- .../views/Components/ComponentsResizer.js | 228 ++++++++---------- 1 file changed, 99 insertions(+), 129 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js b/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js index de339f6a2dd..f97466843ea 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/ComponentsResizer.js @@ -7,8 +7,6 @@ * @flow */ -import type {ElementRef} from 'react'; - import * as React from 'react'; import {useEffect, useLayoutEffect, useReducer, useRef} from 'react'; import { @@ -21,86 +19,6 @@ const LOCAL_STORAGE_KEY = 'React::DevTools::createResizeReducer'; const VERTICAL_MODE_MAX_WIDTH = 600; const MINIMUM_SIZE = 50; -type Props = {| - children: ({ - resizeElementRef: ElementRef, - onResizeStart: () => void, - }) => React$Node, -|}; - -export default function ComponentsResizer({children}: Props) { - const wrapperElementRef = useRef(null); - const resizeElementRef = useRef(null); - const [state, dispatch] = createResizeReducer( - wrapperElementRef, - resizeElementRef, - ); - - const {isResizing} = state; - - const onResizeStart = () => - dispatch({type: 'ACTION_SET_IS_RESIZING', payload: true}); - const onResizeEnd = () => - dispatch({type: 'ACTION_SET_IS_RESIZING', payload: false}); - - const onResize = event => { - const resizeElement = resizeElementRef.current; - const wrapperElement = wrapperElementRef.current; - - if (!isResizing || wrapperElement === null || resizeElement === null) { - return; - } - - event.preventDefault(); - - const orientation = getOrientation(wrapperElementRef); - - const {height, width, left, top} = wrapperElement.getBoundingClientRect(); - - const currentMousePosition = - orientation === 'horizontal' ? event.clientX - left : event.clientY - top; - - const boundaryMin = MINIMUM_SIZE; - const boundaryMax = - orientation === 'horizontal' - ? width - MINIMUM_SIZE - : height - MINIMUM_SIZE; - - const isMousePositionInBounds = - currentMousePosition > boundaryMin && currentMousePosition < boundaryMax; - - if (isMousePositionInBounds) { - const resizedElementDimension = - orientation === 'horizontal' ? width : height; - const actionType = - orientation === 'horizontal' - ? 'ACTION_SET_HORIZONTAL_PERCENTAGE' - : 'ACTION_SET_VERTICAL_PERCENTAGE'; - const percentage = (currentMousePosition / resizedElementDimension) * 100; - - setResizeCSSVariable(resizeElementRef, orientation, percentage); - - dispatch({ - type: actionType, - payload: currentMousePosition / resizedElementDimension, - }); - } - }; - - return ( -
- {children({resizeElementRef, onResizeStart})} -
- ); -} - type Orientation = 'horizontal' | 'vertical'; type ResizeActionType = @@ -162,67 +80,34 @@ function resizeReducer(state: ResizeState, action: ResizeAction): ResizeState { } } -function getOrientation( - wrapperElementRef: ElementRef, -): null | Orientation { - const wrapperElement = wrapperElementRef.current; - if (wrapperElement != null) { - const {width} = wrapperElement.getBoundingClientRect(); - return width > VERTICAL_MODE_MAX_WIDTH ? 'horizontal' : 'vertical'; - } - return null; -} - -function setResizeCSSVariable( - resizeElementRef: ElementRef, - orientation: null | Orientation, - percentage: number, -): void { - const resizeElement = resizeElementRef.current; +type Props = {| + children: ({ + resizeElementRef: React$Ref, + onResizeStart: () => void, + }) => React$Node, +|}; - if (resizeElement !== null && orientation !== null) { - resizeElement.style.setProperty( - `--${orientation}-resize-percentage`, - `${percentage}%`, - ); - } -} +export default function ComponentsResizer({children}: Props) { + const wrapperElementRef = useRef(null); + const resizeElementRef = useRef(null); -function createResizeReducer(wrapperElementRef, resizeElementRef) { const [state, dispatch] = useReducer( resizeReducer, null, initResizeState, ); + const {horizontalPercentage, verticalPercentage} = state; - // Initial set up for the resize percentage CSS variables. useLayoutEffect(() => { - const orientationAndPercentage = { - horizontal: horizontalPercentage, - vertical: verticalPercentage, - }; - - Object.keys(orientationAndPercentage).forEach(orientation => { - setResizeCSSVariable( - resizeElementRef, - orientation, - orientationAndPercentage[orientation] * 100, - ); - }); - }, []); + const resizeElement = resizeElementRef.current; - useLayoutEffect(() => { setResizeCSSVariable( - resizeElementRef, + resizeElement, 'horizontal', horizontalPercentage * 100, ); - setResizeCSSVariable( - resizeElementRef, - 'vertical', - verticalPercentage * 100, - ); + setResizeCSSVariable(resizeElement, 'vertical', verticalPercentage * 100); }, []); useEffect(() => { @@ -239,5 +124,90 @@ function createResizeReducer(wrapperElementRef, resizeElementRef) { return () => clearTimeout(timeoutID); }, [horizontalPercentage, verticalPercentage]); - return [state, dispatch]; + const {isResizing} = state; + + const onResizeStart = () => + dispatch({type: 'ACTION_SET_IS_RESIZING', payload: true}); + const onResizeEnd = () => + dispatch({type: 'ACTION_SET_IS_RESIZING', payload: false}); + + const onResize = event => { + const resizeElement = resizeElementRef.current; + const wrapperElement = wrapperElementRef.current; + + if (!isResizing || wrapperElement === null || resizeElement === null) { + return; + } + + event.preventDefault(); + + const orientation = getOrientation(wrapperElement); + + const {height, width, left, top} = wrapperElement.getBoundingClientRect(); + + const currentMousePosition = + orientation === 'horizontal' ? event.clientX - left : event.clientY - top; + + const boundaryMin = MINIMUM_SIZE; + const boundaryMax = + orientation === 'horizontal' + ? width - MINIMUM_SIZE + : height - MINIMUM_SIZE; + + const isMousePositionInBounds = + currentMousePosition > boundaryMin && currentMousePosition < boundaryMax; + + if (isMousePositionInBounds) { + const resizedElementDimension = + orientation === 'horizontal' ? width : height; + const actionType = + orientation === 'horizontal' + ? 'ACTION_SET_HORIZONTAL_PERCENTAGE' + : 'ACTION_SET_VERTICAL_PERCENTAGE'; + const percentage = (currentMousePosition / resizedElementDimension) * 100; + + setResizeCSSVariable(resizeElement, orientation, percentage); + + dispatch({ + type: actionType, + payload: currentMousePosition / resizedElementDimension, + }); + } + }; + + return ( +
+ {children({resizeElementRef, onResizeStart})} +
+ ); +} + +function getOrientation( + wrapperElement: null | HTMLElement, +): null | Orientation { + if (wrapperElement != null) { + const {width} = wrapperElement.getBoundingClientRect(); + return width > VERTICAL_MODE_MAX_WIDTH ? 'horizontal' : 'vertical'; + } + return null; +} + +function setResizeCSSVariable( + resizeElement: null | HTMLElement, + orientation: null | Orientation, + percentage: number, +): void { + if (resizeElement !== null && orientation !== null) { + resizeElement.style.setProperty( + `--${orientation}-resize-percentage`, + `${percentage}%`, + ); + } }