Skip to content

Commit

Permalink
Fix Flow ref issue
Browse files Browse the repository at this point in the history
  • Loading branch information
bvaughn authored Feb 26, 2020
1 parent 27f5906 commit 267f242
Showing 1 changed file with 99 additions and 129 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
* @flow
*/

import type {ElementRef} from 'react';

import * as React from 'react';
import {useEffect, useLayoutEffect, useReducer, useRef} from 'react';
import {
Expand All @@ -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<HTMLElement>,
onResizeStart: () => void,
}) => React$Node,
|};

export default function ComponentsResizer({children}: Props) {
const wrapperElementRef = useRef<HTMLDivElement>(null);
const resizeElementRef = useRef<HTMLElement>(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 (
<div
ref={wrapperElementRef}
className={styles.ComponentsWrapper}
{...(isResizing && {
onMouseMove: onResize,
onMouseLeave: onResizeEnd,
onMouseUp: onResizeEnd,
})}>
{children({resizeElementRef, onResizeStart})}
</div>
);
}

type Orientation = 'horizontal' | 'vertical';

type ResizeActionType =
Expand Down Expand Up @@ -162,67 +80,34 @@ function resizeReducer(state: ResizeState, action: ResizeAction): ResizeState {
}
}

function getOrientation(
wrapperElementRef: ElementRef<HTMLElement>,
): 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<HTMLElement>,
orientation: null | Orientation,
percentage: number,
): void {
const resizeElement = resizeElementRef.current;
type Props = {|
children: ({
resizeElementRef: React$Ref<HTMLElement>,
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<HTMLElement>(null);
const resizeElementRef = useRef<HTMLElement>(null);

function createResizeReducer(wrapperElementRef, resizeElementRef) {
const [state, dispatch] = useReducer<ResizeState, ResizeAction>(
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(() => {
Expand All @@ -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 (
<div
ref={wrapperElementRef}
className={styles.ComponentsWrapper}
{...(isResizing && {
onMouseMove: onResize,
onMouseLeave: onResizeEnd,
onMouseUp: onResizeEnd,
})}>
{children({resizeElementRef, onResizeStart})}
</div>
);
}

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}%`,
);
}
}

0 comments on commit 267f242

Please sign in to comment.