-
Notifications
You must be signed in to change notification settings - Fork 367
/
ResizableBox.js
98 lines (89 loc) · 3.04 KB
/
ResizableBox.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// @flow
import * as React from 'react';
import type {Node as ReactNode, Element as ReactElement} from 'react';
import PropTypes from 'prop-types';
import Resizable from './Resizable';
import {resizableProps} from "./propTypes";
import type {ResizeCallbackData, ResizableBoxState} from './propTypes';
// ElementConfig gives us an object type where all items present in `defaultProps` are made optional.
// <ResizableBox> does not have defaultProps, so we can use this type to tell Flow that we don't
// care about that and will handle it in <Resizable> instead.
// A <ResizableBox> can also have a `style` property.
type ResizableBoxProps = {|...React.ElementConfig<typeof Resizable>, style?: Object, children?: ReactElement<any>|};
export default class ResizableBox extends React.Component<ResizableBoxProps, ResizableBoxState> {
// PropTypes are identical to <Resizable>, except that children are not strictly required to be present.
static propTypes = {
...resizableProps,
children: PropTypes.element,
};
state: ResizableBoxState = {
width: this.props.width,
height: this.props.height,
propsWidth: this.props.width,
propsHeight: this.props.height,
};
static getDerivedStateFromProps(props: ResizableBoxProps, state: ResizableBoxState): ?ResizableBoxState {
// If parent changes height/width, set that in our state.
if (state.propsWidth !== props.width || state.propsHeight !== props.height) {
return {
width: props.width,
height: props.height,
propsWidth: props.width,
propsHeight: props.height,
};
}
return null;
}
onResize: (e: SyntheticEvent<>, data: ResizeCallbackData) => void = (e, data) => {
const {size} = data;
if (this.props.onResize) {
e.persist?.();
this.setState(size, () => this.props.onResize && this.props.onResize(e, data));
} else {
this.setState(size);
}
};
render(): ReactNode {
// Basic wrapper around a Resizable instance.
// If you use Resizable directly, you are responsible for updating the child component
// with a new width and height.
const {
handle,
handleSize,
onResize,
onResizeStart,
onResizeStop,
draggableOpts,
minConstraints,
maxConstraints,
lockAspectRatio,
axis,
width,
height,
resizeHandles,
style,
transformScale,
...props
} = this.props;
return (
<Resizable
axis={axis}
draggableOpts={draggableOpts}
handle={handle}
handleSize={handleSize}
height={this.state.height}
lockAspectRatio={lockAspectRatio}
maxConstraints={maxConstraints}
minConstraints={minConstraints}
onResizeStart={onResizeStart}
onResize={this.onResize}
onResizeStop={onResizeStop}
resizeHandles={resizeHandles}
transformScale={transformScale}
width={this.state.width}
>
<div {...props} style={{...style, width: this.state.width + 'px', height: this.state.height + 'px'}} />
</Resizable>
);
}
}