Skip to content

Commit 124060d

Browse files
committed
Added basic touch resize functionality
1 parent c776151 commit 124060d

File tree

5 files changed

+58
-30
lines changed

5 files changed

+58
-30
lines changed

demo/src/ui-demo/Resizable.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,12 @@ const AnchoredExample : React.FC<{ spaceSize: number,resizingSpaces: boolean, se
5252

5353
return (
5454
<>
55-
<Space.LeftResizable size={`${props.spaceSize}%`} trackSize={trackSize} className={props.children ? "blue" : "gray"}>
55+
<Space.LeftResizable size={`${props.spaceSize}%`} handleSize={30} trackSize={trackSize} className={props.children ? "blue" : "gray"}>
5656
{Description("Left")}
5757
</Space.LeftResizable>
5858

5959
<Space.Fill>
60-
<Space.TopResizable size={`${props.spaceSize}%`} trackSize={trackSize} className={props.children ? "red" : "blue"}>
60+
<Space.TopResizable size={`${props.spaceSize}%`} handleSize={30} trackSize={trackSize} className={props.children ? "red" : "blue"}>
6161
{Description("Top")}
6262
</Space.TopResizable>
6363
<Space.Fill trackSize={trackSize} className="white">
@@ -74,12 +74,12 @@ const AnchoredExample : React.FC<{ spaceSize: number,resizingSpaces: boolean, se
7474
</Space.Centered>
7575
}
7676
</Space.Fill>
77-
<Space.BottomResizable size={`${props.spaceSize}%`} trackSize={trackSize} className={props.children ? "red" : "blue"}>
77+
<Space.BottomResizable size={`${props.spaceSize}%`} handleSize={30} trackSize={trackSize} className={props.children ? "red" : "blue"}>
7878
{Description("Bottom")}
7979
</Space.BottomResizable>
8080
</Space.Fill>
8181

82-
<Space.RightResizable size={`${props.spaceSize}%`} trackSize={trackSize} className={props.children ? "blue" : "gray"}>
82+
<Space.RightResizable size={`${props.spaceSize}%`} handleSize={30} trackSize={trackSize} className={props.children ? "blue" : "gray"}>
8383
{Description("Right")}
8484
</Space.RightResizable>
8585
</>

demo/src/ui-demo/Scrollable.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const ScrollableDemo = () => {
2323
Header
2424
</Space.Top>
2525
<Space.Fill>
26-
<Space.LeftResizable as="aside" size="20%">
26+
<Space.LeftResizable as="aside" size="20%" handleSize={30}>
2727
<Menu defaultSelectedKeys={[ selectedKey ]} onSelect={e => setSelectedKey(e.key)}>
2828
<Menu.Item key="1">Menu item 1</Menu.Item>
2929
<Menu.Item key="2">Menu item 2</Menu.Item>

demo/src/ui-demo/UI.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const DemoSelection = (props: {
3737

3838
return (
3939
props.sidebarVisible ?
40-
<Space.LeftResizable className="ui-list" size={300} minimumSize={150} style={{ backgroundColor: '#193549' }}>
40+
<Space.LeftResizable className="ui-list" size={300} minimumSize={150} style={{ backgroundColor: '#193549' }} handleSize={30}>
4141
<Space.Fill scrollable={true}>
4242
<ul>
4343
<li className={props.selectedDemo === "resizable" ? "active" : undefined}>

react-spaces/src/Globals/Utils.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,15 @@ export const applyResize = (props: AllProps, state: IState, setState: (stateDelt
114114
}
115115

116116
return { resizeHandle: null, resizeType: null };
117+
}
118+
119+
export const debounce = <F extends ((...args: any) => any)>(func: F, waitFor: number) => {
120+
let timeout: number = 0
121+
122+
const debounced = (...args: any) => {
123+
window.clearTimeout(timeout)
124+
timeout = window.setTimeout(() => func(...args), waitFor)
125+
}
126+
127+
return debounced as (...args: Parameters<F>) => ReturnType<F>
117128
}

react-spaces/src/Resizable.tsx

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as React from 'react';
22
import './Styles.css';
3+
import { debounce } from './Globals/Utils';
34

45
export enum ResizeType {
56
Left = "resize-left",
@@ -20,40 +21,56 @@ interface IProps {
2021
export const Resizable : React.FC<IProps> = (props) => {
2122
const [ adjustedSize, setAdjustedSize ] = React.useState(0);
2223

24+
const resize = (originalX: number, originalY: number, x: number, y: number) => {
25+
const adjustmentX =
26+
Math.min(
27+
Math.max(props.type === ResizeType.Left ? originalX - x : x - originalX, props.minimumAdjust),
28+
props.maximumAdjust || 999999
29+
);
30+
const adjustmentY =
31+
Math.min(
32+
Math.max(props.type === ResizeType.Top ? originalY - y : y - originalY, props.minimumAdjust),
33+
props.maximumAdjust || 999999
34+
);
35+
const adjustment = props.type === ResizeType.Left || props.type === ResizeType.Right ? adjustmentX : adjustmentY;
36+
37+
if (adjustment !== adjustedSize) {
38+
setAdjustedSize(adjustment);
39+
props.onResize(adjustment);
40+
}
41+
}
42+
43+
const startTouchResize = (e: React.TouchEvent<HTMLDivElement>) => {
44+
const originalTouchX = props.type === ResizeType.Left ? e.touches[0].pageX + adjustedSize : e.touches[0].pageX - adjustedSize;
45+
const originalTouchY = props.type === ResizeType.Top ? e.touches[0].pageY + adjustedSize : e.touches[0].pageY - adjustedSize;
46+
47+
const touchResize = (e: TouchEvent) => resize(originalTouchX, originalTouchY, e.touches[0].pageX, e.touches[0].pageY);
48+
const debouncedTouchResize = debounce<typeof touchResize>(touchResize, 10);
49+
const withPreventDefault = (e: TouchEvent) => { e.preventDefault(); e.stopImmediatePropagation(); debouncedTouchResize(e); };
50+
window.addEventListener('touchmove', withPreventDefault);
51+
window.addEventListener('touchend', () => window.removeEventListener('touchmove', withPreventDefault));
52+
e.preventDefault();
53+
e.stopPropagation();
54+
}
55+
2356
const startResize = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
2457
const originalMouseX = props.type === ResizeType.Left ? e.pageX + adjustedSize : e.pageX - adjustedSize;
2558
const originalMouseY = props.type === ResizeType.Top ? e.pageY + adjustedSize : e.pageY - adjustedSize;
2659

27-
const resize = (e: MouseEvent) => {
28-
const adjustmentX =
29-
Math.min(
30-
Math.max(props.type === ResizeType.Left ? originalMouseX - e.pageX : e.pageX - originalMouseX, props.minimumAdjust),
31-
props.maximumAdjust || 999999
32-
);
33-
const adjustmentY =
34-
Math.min(
35-
Math.max(props.type === ResizeType.Top ? originalMouseY - e.pageY : e.pageY - originalMouseY, props.minimumAdjust),
36-
props.maximumAdjust || 999999
37-
);
38-
const adjustment = props.type === ResizeType.Left || props.type === ResizeType.Right ? adjustmentX : adjustmentY;
39-
40-
if (adjustment !== adjustedSize) {
41-
setAdjustedSize(adjustment);
42-
props.onResize(adjustment);
43-
}
44-
}
45-
46-
const stopResize = () => window.removeEventListener('mousemove', resize);
47-
60+
const mouseResize = (e: MouseEvent) => resize(originalMouseX, originalMouseY, e.pageX, e.pageY);
61+
const debouncedMouseResize = debounce<typeof mouseResize>(mouseResize, 10);
62+
const withPreventDefault = (e: MouseEvent) => { e.preventDefault(); e.stopImmediatePropagation(); debouncedMouseResize(e); };
63+
window.addEventListener('mousemove', withPreventDefault);
64+
window.addEventListener('mouseup', () => window.removeEventListener('mousemove', withPreventDefault));
4865
e.preventDefault();
49-
window.addEventListener('mousemove', resize);
50-
window.addEventListener('mouseup', stopResize);
66+
e.stopPropagation();
5167
}
5268

5369
return (
5470
<div
5571
style={{ width: props.width, height: props.height }}
5672
className={`spaces-resize-handle ${props.type}`}
57-
onMouseDown={startResize} />
73+
onMouseDown={startResize}
74+
onTouchStart={startTouchResize} />
5875
)
5976
}

0 commit comments

Comments
 (0)