(
+ resizeReducer,
+ null,
+ initResizeState,
+ );
+
+ const {horizontalPercentage, verticalPercentage} = state;
+
+ useLayoutEffect(() => {
+ const resizeElement = resizeElementRef.current;
+
+ setResizeCSSVariable(
+ resizeElement,
+ 'horizontal',
+ horizontalPercentage * 100,
+ );
+ setResizeCSSVariable(resizeElement, 'vertical', verticalPercentage * 100);
+ }, []);
+
+ useEffect(() => {
+ const timeoutID = setTimeout(() => {
+ localStorageSetItem(
+ LOCAL_STORAGE_KEY,
+ JSON.stringify({
+ horizontalPercentage,
+ verticalPercentage,
+ }),
+ );
+ }, 500);
+
+ return () => clearTimeout(timeoutID);
+ }, [horizontalPercentage, verticalPercentage]);
+
+ 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}%`,
+ );
+ }
+}