Skip to content

Commit c876195

Browse files
authored
Fixup drag stop (#549)
* fix: Remove spaces for testnig * chore: green keep * fix: fix #526 * fix: use pure
1 parent 19e1595 commit c876195

File tree

7 files changed

+223
-147
lines changed

7 files changed

+223
-147
lines changed

fixture.html

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
<head>
44
<style>
5+
html, body {
6+
padding: 0;
7+
margin: 0;
8+
}
59
body {
6-
background: red;
710
width: 100vw;
811
height: 100vh;
912
}

package.json

+13-13
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"scripts": {
1818
"lint": "tslint -c tslint.json 'src/index.tsx'",
1919
"flow": "flow",
20-
"tsc": "tsc -p tsconfig.json",
20+
"tsc": "tsc -p tsconfig.json --skipLibCheck",
2121
"build:prod:main": "rollup -c scripts/prod.js",
2222
"build:prod:es5": "rollup -c scripts/prod.es5.js",
2323
"build": "npm-run-all --serial build:prod:* copy:flow",
@@ -48,23 +48,23 @@
4848
"@babel/preset-typescript": "7.3.3",
4949
"@babel/traverse": "7.4.5",
5050
"@babel/types": "7.4.4",
51-
"@emotion/core": "10.0.10",
51+
"@emotion/core": "10.0.14",
5252
"@storybook/addon-actions": "5.1.3",
5353
"@storybook/addon-info": "5.1.3",
5454
"@storybook/addon-links": "5.1.3",
5555
"@storybook/addon-options": "5.1.3",
5656
"@storybook/react": "5.1.3",
5757
"@types/enzyme": "3.1.16",
58-
"@types/enzyme-adapter-react-16": "1.0.4",
58+
"@types/enzyme-adapter-react-16": "1.0.5",
59+
"@types/node": "^12.0.10",
5960
"@types/react": "16.4.1",
60-
"@types/node": "^10.12.19",
6161
"@types/react-dom": "16.0.11",
6262
"@types/sinon": "7.0.13",
6363
"@types/storybook__addon-actions": "3.4.3",
6464
"@types/storybook__react": "4.0.2",
6565
"avaron": "0.2.0",
6666
"babel-core": "7.0.0-bridge.0",
67-
"babel-eslint": "10.0.1",
67+
"babel-eslint": "10.0.2",
6868
"babel-loader": "8.0.6",
6969
"cpy-cli": "2.0.0",
7070
"enzyme": "3.8.0",
@@ -73,19 +73,19 @@
7373
"light-ts-loader": "1.1.2",
7474
"npm-run-all": "4.1.5",
7575
"prettier": "1.18.2",
76-
"react": "16.8.2",
77-
"react-dom": "16.8.2",
76+
"react": "16.8.6",
77+
"react-dom": "16.8.6",
7878
"react-test-renderer": "16.8.6",
79-
"rollup": "1.15.6",
80-
"rollup-plugin-babel": "4.3.2",
81-
"rollup-plugin-commonjs": "10.0.0",
79+
"rollup": "1.16.4",
80+
"rollup-plugin-babel": "4.3.3",
81+
"rollup-plugin-commonjs": "10.0.1",
8282
"rollup-plugin-node-globals": "1.4.0",
83-
"rollup-plugin-node-resolve": "5.0.3",
83+
"rollup-plugin-node-resolve": "5.2.0",
8484
"rollup-plugin-replace": "2.2.0",
85-
"rollup-plugin-typescript2": "0.21.1",
85+
"rollup-plugin-typescript2": "0.21.2",
8686
"rollup-watch": "4.3.1",
8787
"sinon": "7.3.2",
88-
"tslint": "5.17.0",
88+
"tslint": "5.18.0",
8989
"tslint-eslint-rules": "5.4.0",
9090
"tslint-plugin-prettier": "2.0.1",
9191
"tslint-react": "4.0.0",

src/index.test.tsx

+10-10
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,10 @@ test("should enable dragging only x when axis equals x", async t => {
168168
.simulate("mousedown", { clientX: 0, clientY: 0 });
169169
mouseMove(200, 220);
170170
t.is(onDrag.callCount, 1);
171-
t.not((rnd.getDOMNode().getAttribute("style") || "").indexOf("transform: translate(308px, 100px)"), -1);
171+
t.not((rnd.getDOMNode().getAttribute("style") || "").indexOf("transform: translate(300px, 100px)"), -1);
172172
});
173173

174-
test("should enable dragging only y when axis equals y", async t => {
174+
test("xdragging only y when axis equals y", async t => {
175175
const onDrag = spy();
176176
const rnd = mount(<Rnd onDrag={onDrag} dragAxis="y" default={{ x: 100, y: 100, width: 100, height: 100 }} />, {
177177
attachTo: document.querySelector("div"),
@@ -182,7 +182,7 @@ test("should enable dragging only y when axis equals y", async t => {
182182
.simulate("mousedown", { clientX: 0, clientY: 0 });
183183
mouseMove(200, 220);
184184
t.is(onDrag.callCount, 1);
185-
t.not((rnd.getDOMNode().getAttribute("style") || "").indexOf("transform: translate(100px, 328px)"), -1);
185+
t.not((rnd.getDOMNode().getAttribute("style") || "").indexOf("transform: translate(100px, 320px)"), -1);
186186
});
187187

188188
test("should enable dragging both x & y when axis equals both", async t => {
@@ -196,7 +196,7 @@ test("should enable dragging both x & y when axis equals both", async t => {
196196
.simulate("mousedown", { clientX: 0, clientY: 0 });
197197
mouseMove(200, 220);
198198
t.is(onDrag.callCount, 1);
199-
t.not((rnd.getDOMNode().getAttribute("style") || "").indexOf("transform: translate(308px, 328px)"), -1);
199+
t.not((rnd.getDOMNode().getAttribute("style") || "").indexOf("transform: translate(300px, 320px)"), -1);
200200
});
201201

202202
test("should snap when dragging smaller than threshold", async t => {
@@ -208,7 +208,7 @@ test("should snap when dragging smaller than threshold", async t => {
208208
.at(0)
209209
.simulate("mousedown", { clientX: 0, clientY: 0 });
210210
mouseMove(14, 49);
211-
t.not((rnd.getDOMNode().getAttribute("style") || "").indexOf("transform: translate(108px, 108px)"), -1);
211+
t.not((rnd.getDOMNode().getAttribute("style") || "").indexOf("transform: translate(100px, 100px)"), -1);
212212
});
213213

214214
test("should snap when dragging larger than threshold", async t => {
@@ -220,7 +220,7 @@ test("should snap when dragging larger than threshold", async t => {
220220
.at(0)
221221
.simulate("mousedown", { clientX: 0, clientY: 0 });
222222
mouseMove(15, 50);
223-
t.not((rnd.getDOMNode().getAttribute("style") || "").indexOf("transform: translate(138px, 208px)"), -1);
223+
t.not((rnd.getDOMNode().getAttribute("style") || "").indexOf("transform: translate(130px, 200px)"), -1);
224224
});
225225

226226
test("should limit position by parent bounds", async t => {
@@ -244,7 +244,7 @@ test("should limit position by parent bounds", async t => {
244244
.childAt(0)
245245
.getDOMNode()
246246
.getAttribute("style") || ""
247-
).indexOf("transform: translate(708px, 508px)"),
247+
).indexOf("transform: translate(700px, 500px)"),
248248
-1,
249249
);
250250
});
@@ -275,7 +275,7 @@ test("should limit position by selector bounds", async t => {
275275
.childAt(0)
276276
.getDOMNode()
277277
.getAttribute("style") || ""
278-
).indexOf("translate(908px, 708px)"),
278+
).indexOf("translate(900px, 700px)"),
279279
-1,
280280
);
281281
});
@@ -468,7 +468,7 @@ test("should move x when resizing left", async t => {
468468
t.deepEqual(onResize.getCall(0).args[2].clientWidth, 150);
469469
t.deepEqual(onResize.getCall(0).args[2].clientHeight, 100);
470470
t.deepEqual(onResize.getCall(0).args[3], { width: 50, height: 0 });
471-
t.not((rnd.getDOMNode().getAttribute("style") || "").indexOf("transform: translate(58px, 108px)"), -1);
471+
t.not((rnd.getDOMNode().getAttribute("style") || "").indexOf("transform: translate(50px, 100px)"), -1);
472472
});
473473

474474
test("should move y when resizing top", async t => {
@@ -512,7 +512,7 @@ test("should move y when resizing top", async t => {
512512
t.deepEqual(onResize.getCall(0).args[2].clientWidth, 100);
513513
t.deepEqual(onResize.getCall(0).args[2].clientHeight, 150);
514514
t.deepEqual(onResize.getCall(0).args[3], { width: 0, height: 50 });
515-
t.not((rnd.getDOMNode().getAttribute("style") || "").indexOf("transform: translate(108px, 58px)"), -1);
515+
t.not((rnd.getDOMNode().getAttribute("style") || "").indexOf("transform: translate(100px, 50px)"), -1);
516516
});
517517

518518
test("should snapped by original grid when x axis resizing smaller then threshold", async t => {

src/index.tsx

+42-37
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ export interface Props {
118118
resizeGrid?: Grid;
119119
bounds?: string;
120120
onMouseDown?: (e: MouseEvent) => void;
121+
onMouseUp?: (e: MouseEvent) => void;
121122
onResizeStart?: RndResizeStartCallback;
122123
onResize?: RndResizeCallback;
123124
onResizeStop?: RndResizeCallback;
@@ -169,7 +170,7 @@ interface DefaultProps {
169170
scale: number;
170171
}
171172

172-
export class Rnd extends React.Component<Props, State> {
173+
export class Rnd extends React.PureComponent<Props, State> {
173174
public static defaultProps: DefaultProps = {
174175
maxWidth: Number.MAX_SAFE_INTEGER,
175176
maxHeight: Number.MAX_SAFE_INTEGER,
@@ -183,7 +184,8 @@ export class Rnd extends React.Component<Props, State> {
183184
};
184185
resizable!: Resizable;
185186
draggable!: $TODO; // Draggable;
186-
isResizing = false;
187+
resizing = false;
188+
resizingPosition = { x: 0, y: 0 };
187189

188190
constructor(props: Props) {
189191
super(props);
@@ -346,7 +348,8 @@ export class Rnd extends React.Component<Props, State> {
346348
elementRef: HTMLDivElement,
347349
) {
348350
e.stopPropagation();
349-
this.isResizing = true;
351+
this.resizing = true;
352+
350353
const scale = this.props.scale as number;
351354
this.setState({
352355
original: this.getDraggablePosition(),
@@ -445,32 +448,28 @@ export class Rnd extends React.Component<Props, State> {
445448
const offset = this.getOffsetFromParent();
446449
if (/left/i.test(direction)) {
447450
x = this.state.original.x - delta.width;
448-
// INFO: If uncontrolled component, apply x position by resize to draggable.
449-
if (!this.props.position) {
450-
this.draggable.setState({ x });
451-
}
451+
// INFO: Apply x position by resize to draggable.
452+
this.draggable.setState({ x });
452453
x += offset.left;
453454
}
454455
if (/top/i.test(direction)) {
455456
y = this.state.original.y - delta.height;
456-
// INFO: If uncontrolled component, apply y position by resize to draggable.
457-
if (!this.props.position) {
458-
this.draggable.setState({ y });
459-
}
457+
// INFO: Apply x position by resize to draggable.
458+
this.draggable.setState({ y });
460459
y += offset.top;
461460
}
462-
if (this.props.onResize) {
463-
if (typeof x === "undefined") {
464-
x = this.getDraggablePosition().x + offset.left;
465-
}
466-
if (typeof y === "undefined") {
467-
y = this.getDraggablePosition().y + offset.top;
468-
}
469-
this.props.onResize(e, direction, elementRef, delta, {
470-
x,
471-
y,
472-
});
461+
if (typeof x === "undefined") {
462+
x = this.getDraggablePosition().x + offset.left;
473463
}
464+
if (typeof y === "undefined") {
465+
y = this.getDraggablePosition().y + offset.top;
466+
}
467+
this.resizingPosition = { x, y };
468+
if (!this.props.onResize) return;
469+
this.props.onResize(e, direction, elementRef, delta, {
470+
x,
471+
y,
472+
});
474473
}
475474

476475
onResizeStop(
@@ -479,12 +478,11 @@ export class Rnd extends React.Component<Props, State> {
479478
elementRef: HTMLDivElement,
480479
delta: { height: number; width: number },
481480
) {
482-
this.isResizing = false;
481+
this.resizing = false;
483482
const { maxWidth, maxHeight } = this.getMaxSizesFromProps();
484483
this.setState({ maxWidth, maxHeight });
485484
if (this.props.onResizeStop) {
486-
const position: Position = this.getDraggablePosition();
487-
this.props.onResizeStop(e, direction, elementRef, delta, position);
485+
this.props.onResizeStop(e, direction, elementRef, delta, this.resizingPosition);
488486
}
489487
}
490488

@@ -518,13 +516,24 @@ export class Rnd extends React.Component<Props, State> {
518516
};
519517
}
520518

519+
refDraggable = (c: $TODO) => {
520+
if (!c) return;
521+
this.draggable = c;
522+
};
523+
524+
refResizable = (c: Resizable | null) => {
525+
if (!c) return;
526+
this.resizable = c;
527+
};
528+
521529
render() {
522530
const {
523531
disableDragging,
524532
style,
525533
dragHandleClassName,
526534
position,
527535
onMouseDown,
536+
onMouseUp,
528537
dragAxis,
529538
dragGrid,
530539
bounds,
@@ -564,34 +573,30 @@ export class Rnd extends React.Component<Props, State> {
564573
y: position.y - top,
565574
};
566575
}
576+
// INFO: Make uncontorolled component when resizing to control position by setPostion.
577+
const pos = this.resizing ? undefined : draggablePosition
567578
return (
568579
<Draggable
569-
ref={(c: $TODO) => {
570-
if (!c) return;
571-
this.draggable = c;
572-
}}
580+
ref={this.refDraggable}
573581
handle={dragHandleClassName ? `.${dragHandleClassName}` : undefined}
574582
defaultPosition={defaultValue}
575583
onMouseDown={onMouseDown}
584+
onMouseUp={onMouseUp}
576585
onStart={this.onDragStart}
577586
onDrag={this.onDrag}
578587
onStop={this.onDragStop}
579588
axis={dragAxis}
580589
disabled={disableDragging}
581590
grid={dragGrid}
582591
bounds={bounds ? this.state.bounds : undefined}
583-
position={draggablePosition}
592+
position={pos}
584593
enableUserSelectHack={enableUserSelectHack}
585594
cancel={cancel}
586595
scale={scale}
587596
>
588597
<Resizable
589598
{...resizableProps}
590-
ref={c => {
591-
if (c) {
592-
this.resizable = c;
593-
}
594-
}}
599+
ref={this.refResizable}
595600
defaultSize={defaultValue}
596601
size={this.props.size}
597602
enable={enableResizing}
@@ -601,8 +606,8 @@ export class Rnd extends React.Component<Props, State> {
601606
style={innerStyle}
602607
minWidth={this.props.minWidth}
603608
minHeight={this.props.minHeight}
604-
maxWidth={this.isResizing ? this.state.maxWidth : this.props.maxWidth}
605-
maxHeight={this.isResizing ? this.state.maxHeight : this.props.maxHeight}
609+
maxWidth={this.resizing ? this.state.maxWidth : this.props.maxWidth}
610+
maxHeight={this.resizing ? this.state.maxHeight : this.props.maxHeight}
606611
grid={resizeGrid}
607612
handleWrapperClass={resizeHandleWrapperClass}
608613
handleWrapperStyle={resizeHandleWrapperStyle}

stories/basic/controlled.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export default class Example extends React.Component<{}, State> {
3535
onDragStop={(e, d) => {
3636
this.setState({ x: d.x, y: d.y });
3737
}}
38-
onResize={(e, direction, ref, delta, position) => {
38+
onResizeStop={(e, direction, ref, delta, position) => {
3939
this.setState({
4040
width: ref.offsetWidth,
4141
height: ref.offsetHeight,

tslint.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"no-reference": true,
2222
"one-line": [true, "check-whitespace"],
2323
"quotemark": [true, "double"],
24-
"semicolon": [true, "always"],
24+
"semicolon": [false, "always"],
2525
"triple-equals": [true, "allow-null-check"],
2626
"typedef-whitespace": [
2727
true,

0 commit comments

Comments
 (0)