react-resizable 3.1.3 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -30
- package/build/Resizable.d.ts +29 -0
- package/build/Resizable.js +56 -52
- package/build/ResizableBox.d.ts +18 -0
- package/build/ResizableBox.js +20 -27
- package/build/index.d.ts +3 -0
- package/build/index.js +9 -0
- package/build/propTypes.d.ts +55 -0
- package/build/propTypes.js +3 -4
- package/build/utils.d.ts +2 -0
- package/build/utils.js +1 -1
- package/package.json +31 -24
- package/build/Resizable.js.flow +0 -224
- package/build/ResizableBox.js.flow +0 -98
- package/build/propTypes.js.flow +0 -161
- package/build/utils.js.flow +0 -14
package/README.md
CHANGED
|
@@ -11,11 +11,12 @@ A simple widget that can be resized via one or more handles.
|
|
|
11
11
|
You can either use the `<Resizable>` element directly, or use the much simpler `<ResizableBox>` element.
|
|
12
12
|
|
|
13
13
|
See the example and associated code in [ExampleLayout](https://github.com/react-grid-layout/react-resizable/blob/master/examples/ExampleLayout.js) and
|
|
14
|
-
[ResizableBox](https://github.com/react-grid-layout/react-resizable/blob/master/lib/ResizableBox.
|
|
14
|
+
[ResizableBox](https://github.com/react-grid-layout/react-resizable/blob/master/lib/ResizableBox.tsx) for more details.
|
|
15
15
|
|
|
16
16
|
## Table of Contents
|
|
17
17
|
|
|
18
18
|
- [Installation](#installation)
|
|
19
|
+
- [TypeScript](#typescript)
|
|
19
20
|
- [Compatibility](#compatibility)
|
|
20
21
|
- [Usage](#usage)
|
|
21
22
|
- [Resizable](#resizable)
|
|
@@ -47,20 +48,59 @@ Or import it in your CSS:
|
|
|
47
48
|
|
|
48
49
|
If you're using a bundler that doesn't support CSS imports, you can find the styles at `node_modules/react-resizable/css/styles.css` and include them manually.
|
|
49
50
|
|
|
51
|
+
## TypeScript
|
|
52
|
+
|
|
53
|
+
As of `4.0.0`, the library is authored in TypeScript and ships bundled type
|
|
54
|
+
declarations in `build/*.d.ts`. You **do not** need to install
|
|
55
|
+
`@types/react-resizable`; if you previously installed it, remove it so the
|
|
56
|
+
bundled types take precedence:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm uninstall @types/react-resizable
|
|
60
|
+
# or
|
|
61
|
+
yarn remove @types/react-resizable
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Public types are re-exported from the package root:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import {
|
|
68
|
+
Resizable,
|
|
69
|
+
ResizableBox,
|
|
70
|
+
// types
|
|
71
|
+
type ResizeCallbackData,
|
|
72
|
+
type ResizeHandleAxis,
|
|
73
|
+
type Axis,
|
|
74
|
+
type Props as ResizableProps,
|
|
75
|
+
} from 'react-resizable';
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Flow
|
|
79
|
+
|
|
80
|
+
Flow is no longer supported as of `4.0.0`. Earlier versions shipped
|
|
81
|
+
`*.js.flow` sidecar files generated from the Flow-annotated source; those
|
|
82
|
+
have been removed.
|
|
83
|
+
|
|
84
|
+
If you still need Flow types, you can vendor the last Flow-annotated source
|
|
85
|
+
locally from the [`3.2.0` tag](https://github.com/react-grid-layout/react-resizable/tree/db2e37eda85fb21b1864e36b01c4922452f28418/lib).
|
|
86
|
+
They will not be updated to reflect changes landing after `4.0.0`. The
|
|
87
|
+
official recommendation is to migrate to TypeScript.
|
|
88
|
+
|
|
50
89
|
## Compatibility
|
|
51
90
|
|
|
52
|
-
| Version | React Version |
|
|
53
|
-
|
|
54
|
-
| [
|
|
55
|
-
|
|
|
56
|
-
|
|
|
91
|
+
| Version | React Version | Types |
|
|
92
|
+
|---------|---------------|----------------|
|
|
93
|
+
| [4.x](https://github.com/react-grid-layout/react-resizable/blob/master/CHANGELOG.md#400-may-12-2026) | `>= 16.3` | TypeScript (bundled) |
|
|
94
|
+
| [3.x](https://github.com/react-grid-layout/react-resizable/blob/master/CHANGELOG.md#300-may-10-2021) | `>= 16.3` | Flow (`*.js.flow`) |
|
|
95
|
+
| 2.x | Skipped | — |
|
|
96
|
+
| [1.x](https://github.com/react-grid-layout/react-resizable/blob/master/CHANGELOG.md#1111-mar-5-2021) | `14 - 17` | Flow |
|
|
57
97
|
|
|
58
98
|
## Usage
|
|
59
99
|
|
|
60
100
|
This package has two major exports:
|
|
61
101
|
|
|
62
|
-
* [`<Resizable>`](https://github.com/react-grid-layout/react-resizable/blob/master/lib/Resizable.
|
|
63
|
-
* [`<ResizableBox>`](https://github.com/react-grid-layout/react-resizable/blob/master/lib/ResizableBox.
|
|
102
|
+
* [`<Resizable>`](https://github.com/react-grid-layout/react-resizable/blob/master/lib/Resizable.tsx): A raw component that does not have state. Use as a building block for larger components, by listening to its callbacks and setting its props.
|
|
103
|
+
* [`<ResizableBox>`](https://github.com/react-grid-layout/react-resizable/blob/master/lib/ResizableBox.tsx): A simple `<div {...props} />` element that manages basic state. Convenient for simple use-cases.
|
|
64
104
|
|
|
65
105
|
### `<Resizable>`
|
|
66
106
|
|
|
@@ -124,43 +164,46 @@ class Example extends React.Component {
|
|
|
124
164
|
|
|
125
165
|
These props apply to both `<Resizable>` and `<ResizableBox>`. Unknown props that are not in the list below will be passed to the child component.
|
|
126
166
|
|
|
127
|
-
```
|
|
167
|
+
```ts
|
|
128
168
|
type ResizeCallbackData = {
|
|
129
|
-
node: HTMLElement
|
|
130
|
-
size: {width: number
|
|
131
|
-
handle: ResizeHandleAxis
|
|
169
|
+
node: HTMLElement;
|
|
170
|
+
size: {width: number; height: number};
|
|
171
|
+
handle: ResizeHandleAxis;
|
|
132
172
|
};
|
|
133
173
|
|
|
134
174
|
type ResizeHandleAxis = 's' | 'w' | 'e' | 'n' | 'sw' | 'nw' | 'se' | 'ne';
|
|
135
175
|
|
|
136
176
|
type ResizableProps = {
|
|
137
|
-
children: React.
|
|
138
|
-
width: number
|
|
139
|
-
height: number
|
|
177
|
+
children: React.ReactElement<any>;
|
|
178
|
+
width: number;
|
|
179
|
+
height: number;
|
|
140
180
|
// Either a ReactElement to be used as handle, or a function
|
|
141
181
|
// returning an element that is fed the handle's location as its first argument.
|
|
142
|
-
handle
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
182
|
+
handle?:
|
|
183
|
+
| React.ReactElement<any>
|
|
184
|
+
| ((resizeHandle: ResizeHandleAxis, ref: React.RefObject<HTMLElement>) => React.ReactElement<any>);
|
|
185
|
+
// If you change this, be sure to update your css. Default: [20, 20].
|
|
186
|
+
handleSize?: [number, number];
|
|
187
|
+
lockAspectRatio?: boolean; // default: false
|
|
188
|
+
axis?: 'both' | 'x' | 'y' | 'none'; // default: 'both'
|
|
189
|
+
minConstraints?: [number, number]; // default: [20, 20]
|
|
190
|
+
maxConstraints?: [number, number]; // default: [Infinity, Infinity]
|
|
191
|
+
onResizeStop?: (e: React.SyntheticEvent, data: ResizeCallbackData) => any;
|
|
192
|
+
onResizeStart?: (e: React.SyntheticEvent, data: ResizeCallbackData) => any;
|
|
193
|
+
onResize?: (e: React.SyntheticEvent, data: ResizeCallbackData) => any;
|
|
194
|
+
// Forwarded to react-draggable's <DraggableCore>.
|
|
195
|
+
draggableOpts?: Partial<React.ComponentProps<typeof import('react-draggable').DraggableCore>>;
|
|
196
|
+
resizeHandles?: ResizeHandleAxis[]; // default: ['se']
|
|
154
197
|
// If `transform: scale(n)` is set on the parent, this should be set to `n`.
|
|
155
|
-
transformScale?: number
|
|
198
|
+
transformScale?: number; // default: 1
|
|
156
199
|
};
|
|
157
200
|
```
|
|
158
201
|
|
|
159
202
|
The following props can also be used on `<ResizableBox>`:
|
|
160
203
|
|
|
161
|
-
```
|
|
204
|
+
```ts
|
|
162
205
|
{
|
|
163
|
-
style?:
|
|
206
|
+
style?: React.CSSProperties; // styles the returned <div />
|
|
164
207
|
}
|
|
165
208
|
```
|
|
166
209
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { ResizeHandleAxis, DefaultProps, Props, DragCallbackData } from './propTypes';
|
|
3
|
+
export default class Resizable extends React.Component<Props, {}> {
|
|
4
|
+
static propTypes: {
|
|
5
|
+
[key: string]: any;
|
|
6
|
+
};
|
|
7
|
+
static defaultProps: DefaultProps;
|
|
8
|
+
handleRefs: {
|
|
9
|
+
[key in ResizeHandleAxis]?: React.RefObject<HTMLElement>;
|
|
10
|
+
};
|
|
11
|
+
lastHandleRect: DOMRect | null;
|
|
12
|
+
slack: [number, number] | null;
|
|
13
|
+
lastSize: {
|
|
14
|
+
width: number;
|
|
15
|
+
height: number;
|
|
16
|
+
} | null;
|
|
17
|
+
componentWillUnmount(): void;
|
|
18
|
+
resetData(): void;
|
|
19
|
+
runConstraints(width: number, height: number): [number, number];
|
|
20
|
+
/**
|
|
21
|
+
* Wrapper around drag events to provide more useful data.
|
|
22
|
+
*
|
|
23
|
+
* @param {String} handlerName Handler name to wrap.
|
|
24
|
+
* @return {Function} Handler function.
|
|
25
|
+
*/
|
|
26
|
+
resizeHandler(handlerName: 'onResize' | 'onResizeStart' | 'onResizeStop', axis: ResizeHandleAxis): (e: React.SyntheticEvent, data: DragCallbackData) => void;
|
|
27
|
+
renderResizeHandle(handleAxis: ResizeHandleAxis, ref: React.RefObject<HTMLElement>): React.ReactNode;
|
|
28
|
+
render(): React.ReactNode;
|
|
29
|
+
}
|
package/build/Resizable.js
CHANGED
|
@@ -9,7 +9,6 @@ var _propTypes = require("./propTypes");
|
|
|
9
9
|
const _excluded = ["children", "className", "draggableOpts", "width", "height", "handle", "handleSize", "lockAspectRatio", "axis", "minConstraints", "maxConstraints", "onResize", "onResizeStop", "onResizeStart", "resizeHandles", "transformScale"];
|
|
10
10
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
11
11
|
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
12
|
-
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
|
|
13
12
|
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
14
13
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
15
14
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
@@ -35,11 +34,10 @@ class Resizable extends React.Component {
|
|
|
35
34
|
|
|
36
35
|
// Clamp width and height within provided constraints
|
|
37
36
|
runConstraints(width, height) {
|
|
38
|
-
const
|
|
39
|
-
minConstraints,
|
|
40
|
-
maxConstraints,
|
|
41
|
-
lockAspectRatio
|
|
42
|
-
} = this.props;
|
|
37
|
+
const _this$props = this.props,
|
|
38
|
+
minConstraints = _this$props.minConstraints,
|
|
39
|
+
maxConstraints = _this$props.maxConstraints,
|
|
40
|
+
lockAspectRatio = _this$props.lockAspectRatio;
|
|
43
41
|
// short circuit
|
|
44
42
|
if (!minConstraints && !maxConstraints && !lockAspectRatio) return [width, height];
|
|
45
43
|
|
|
@@ -59,12 +57,15 @@ class Resizable extends React.Component {
|
|
|
59
57
|
width = height * ratio;
|
|
60
58
|
}
|
|
61
59
|
}
|
|
62
|
-
const
|
|
60
|
+
const oldW = width,
|
|
61
|
+
oldH = height;
|
|
63
62
|
|
|
64
63
|
// Add slack to the values used to calculate bound position. This will ensure that if
|
|
65
64
|
// we start removing slack, the element won't react to it right away until it's been
|
|
66
65
|
// completely removed.
|
|
67
|
-
|
|
66
|
+
const _ref = this.slack || [0, 0],
|
|
67
|
+
slackW = _ref[0],
|
|
68
|
+
slackH = _ref[1];
|
|
68
69
|
width += slackW;
|
|
69
70
|
height += slackH;
|
|
70
71
|
if (minConstraints) {
|
|
@@ -88,12 +89,11 @@ class Resizable extends React.Component {
|
|
|
88
89
|
* @return {Function} Handler function.
|
|
89
90
|
*/
|
|
90
91
|
resizeHandler(handlerName, axis) {
|
|
91
|
-
return (e,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
deltaX,
|
|
95
|
-
deltaY
|
|
96
|
-
} = _ref;
|
|
92
|
+
return (e, _ref2) => {
|
|
93
|
+
var _this$lastSize$width, _this$lastSize, _this$lastSize$height, _this$lastSize2;
|
|
94
|
+
let node = _ref2.node,
|
|
95
|
+
deltaX = _ref2.deltaX,
|
|
96
|
+
deltaY = _ref2.deltaY;
|
|
97
97
|
// Reset data in case it was left over somehow (should not be possible)
|
|
98
98
|
if (handlerName === 'onResizeStart') this.resetData();
|
|
99
99
|
|
|
@@ -132,21 +132,29 @@ class Resizable extends React.Component {
|
|
|
132
132
|
if (axisV === 'n') deltaY = -deltaY;
|
|
133
133
|
|
|
134
134
|
// Update w/h by the deltas. Also factor in transformScale.
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
// Use lastSize (if available) instead of props to avoid losing deltas
|
|
136
|
+
// when React can't re-render between consecutive mouse events.
|
|
137
|
+
const baseWidth = (_this$lastSize$width = (_this$lastSize = this.lastSize) == null ? void 0 : _this$lastSize.width) != null ? _this$lastSize$width : this.props.width;
|
|
138
|
+
const baseHeight = (_this$lastSize$height = (_this$lastSize2 = this.lastSize) == null ? void 0 : _this$lastSize2.height) != null ? _this$lastSize$height : this.props.height;
|
|
139
|
+
let width = baseWidth + (canDragX ? deltaX / this.props.transformScale : 0);
|
|
140
|
+
let height = baseHeight + (canDragY ? deltaY / this.props.transformScale : 0);
|
|
137
141
|
|
|
138
142
|
// Run user-provided constraints.
|
|
139
|
-
[width, height] = this.runConstraints(width, height);
|
|
140
|
-
|
|
141
143
|
// For onResizeStop, use the last size from onResize rather than recalculating.
|
|
142
144
|
// This avoids issues where props.width/height are stale due to React's batched updates.
|
|
145
|
+
var _this$runConstraints = this.runConstraints(width, height);
|
|
146
|
+
width = _this$runConstraints[0];
|
|
147
|
+
height = _this$runConstraints[1];
|
|
143
148
|
if (handlerName === 'onResizeStop' && this.lastSize) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
} = this.lastSize);
|
|
149
|
+
var _this$lastSize3 = this.lastSize;
|
|
150
|
+
width = _this$lastSize3.width;
|
|
151
|
+
height = _this$lastSize3.height;
|
|
148
152
|
}
|
|
149
|
-
|
|
153
|
+
|
|
154
|
+
// Compare against the base (lastSize-or-props) so that callbacks correctly
|
|
155
|
+
// suppress when the net delta is zero, even if props are stale relative to
|
|
156
|
+
// the accumulated lastSize.
|
|
157
|
+
const dimensionsChanged = width !== baseWidth || height !== baseHeight;
|
|
150
158
|
|
|
151
159
|
// Store the size for use in onResizeStop. We do this after the onResizeStop check
|
|
152
160
|
// above so we don't overwrite the stored value with a potentially stale calculation.
|
|
@@ -162,7 +170,7 @@ class Resizable extends React.Component {
|
|
|
162
170
|
// Don't call 'onResize' if dimensions haven't changed.
|
|
163
171
|
const shouldSkipCb = handlerName === 'onResize' && !dimensionsChanged;
|
|
164
172
|
if (cb && !shouldSkipCb) {
|
|
165
|
-
e.persist
|
|
173
|
+
e.persist == null || e.persist();
|
|
166
174
|
cb(e, {
|
|
167
175
|
node,
|
|
168
176
|
size: {
|
|
@@ -181,13 +189,11 @@ class Resizable extends React.Component {
|
|
|
181
189
|
// Render a resize handle given an axis & DOM ref. Ref *must* be attached for
|
|
182
190
|
// the underlying draggable library to work properly.
|
|
183
191
|
renderResizeHandle(handleAxis, ref) {
|
|
184
|
-
const
|
|
185
|
-
handle
|
|
186
|
-
} = this.props;
|
|
192
|
+
const handle = this.props.handle;
|
|
187
193
|
// No handle provided, make the default
|
|
188
194
|
if (!handle) {
|
|
189
195
|
return /*#__PURE__*/React.createElement("span", {
|
|
190
|
-
className:
|
|
196
|
+
className: "react-resizable-handle react-resizable-handle-" + handleAxis,
|
|
191
197
|
ref: ref
|
|
192
198
|
});
|
|
193
199
|
}
|
|
@@ -207,40 +213,38 @@ class Resizable extends React.Component {
|
|
|
207
213
|
}
|
|
208
214
|
render() {
|
|
209
215
|
// Pass along only props not meant for the `<Resizable>`.`
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
transformScale
|
|
229
|
-
} = _this$props,
|
|
230
|
-
p = _objectWithoutProperties(_this$props, _excluded);
|
|
216
|
+
const _this$props2 = this.props,
|
|
217
|
+
children = _this$props2.children,
|
|
218
|
+
className = _this$props2.className,
|
|
219
|
+
draggableOpts = _this$props2.draggableOpts,
|
|
220
|
+
width = _this$props2.width,
|
|
221
|
+
height = _this$props2.height,
|
|
222
|
+
handle = _this$props2.handle,
|
|
223
|
+
handleSize = _this$props2.handleSize,
|
|
224
|
+
lockAspectRatio = _this$props2.lockAspectRatio,
|
|
225
|
+
axis = _this$props2.axis,
|
|
226
|
+
minConstraints = _this$props2.minConstraints,
|
|
227
|
+
maxConstraints = _this$props2.maxConstraints,
|
|
228
|
+
onResize = _this$props2.onResize,
|
|
229
|
+
onResizeStop = _this$props2.onResizeStop,
|
|
230
|
+
onResizeStart = _this$props2.onResizeStart,
|
|
231
|
+
resizeHandles = _this$props2.resizeHandles,
|
|
232
|
+
transformScale = _this$props2.transformScale,
|
|
233
|
+
p = _objectWithoutPropertiesLoose(_this$props2, _excluded);
|
|
231
234
|
|
|
232
235
|
// What we're doing here is getting the child of this element, and cloning it with this element's props.
|
|
233
236
|
// We are then defining its children as:
|
|
234
237
|
// 1. Its original children (resizable's child's children), and
|
|
235
238
|
// 2. One or more draggable handles.
|
|
236
239
|
return (0, _utils.cloneElement)(children, _objectSpread(_objectSpread({}, p), {}, {
|
|
237
|
-
className:
|
|
240
|
+
className: (className ? className + " " : '') + "react-resizable",
|
|
238
241
|
children: [...React.Children.toArray(children.props.children), ...resizeHandles.map(handleAxis => {
|
|
242
|
+
var _this$handleRefs$hand;
|
|
239
243
|
// Create a ref to the handle so that `<DraggableCore>` doesn't have to use ReactDOM.findDOMNode().
|
|
240
|
-
const ref = this.handleRefs[handleAxis]
|
|
244
|
+
const ref = (_this$handleRefs$hand = this.handleRefs[handleAxis]) != null ? _this$handleRefs$hand : this.handleRefs[handleAxis] = /*#__PURE__*/React.createRef();
|
|
241
245
|
return /*#__PURE__*/React.createElement(_reactDraggable.DraggableCore, _extends({}, draggableOpts, {
|
|
242
246
|
nodeRef: ref,
|
|
243
|
-
key:
|
|
247
|
+
key: "resizableHandle-" + handleAxis,
|
|
244
248
|
onStop: this.resizeHandler('onResizeStop', handleAxis),
|
|
245
249
|
onStart: this.resizeHandler('onResizeStart', handleAxis),
|
|
246
250
|
onDrag: this.resizeHandler('onResize', handleAxis)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import type { Props as ResizableProps, ResizeCallbackData, ResizableBoxState } from './propTypes';
|
|
4
|
+
type ResizableBoxProps = Omit<ResizableProps, 'children'> & {
|
|
5
|
+
style?: React.CSSProperties;
|
|
6
|
+
children?: React.ReactElement<any>;
|
|
7
|
+
className?: string | null;
|
|
8
|
+
};
|
|
9
|
+
export default class ResizableBox extends React.Component<ResizableBoxProps, ResizableBoxState> {
|
|
10
|
+
static propTypes: {
|
|
11
|
+
children: PropTypes.Requireable<PropTypes.ReactElementLike>;
|
|
12
|
+
};
|
|
13
|
+
state: ResizableBoxState;
|
|
14
|
+
static getDerivedStateFromProps(props: ResizableBoxProps, state: ResizableBoxState): ResizableBoxState | null;
|
|
15
|
+
onResize: (e: React.SyntheticEvent, data: ResizeCallbackData) => void;
|
|
16
|
+
render(): React.ReactNode;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
package/build/ResizableBox.js
CHANGED
|
@@ -15,12 +15,9 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
15
15
|
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
16
16
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
17
17
|
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
18
|
-
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
|
|
19
18
|
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
// care about that and will handle it in <Resizable> instead.
|
|
23
|
-
// A <ResizableBox> can also have a `style` property.
|
|
19
|
+
// <ResizableBox> does not have defaultProps, so we make all of <Resizable>'s defaults optional here
|
|
20
|
+
// and add an optional `style` property.
|
|
24
21
|
|
|
25
22
|
class ResizableBox extends React.Component {
|
|
26
23
|
constructor() {
|
|
@@ -32,11 +29,9 @@ class ResizableBox extends React.Component {
|
|
|
32
29
|
propsHeight: this.props.height
|
|
33
30
|
};
|
|
34
31
|
this.onResize = (e, data) => {
|
|
35
|
-
const
|
|
36
|
-
size
|
|
37
|
-
} = data;
|
|
32
|
+
const size = data.size;
|
|
38
33
|
if (this.props.onResize) {
|
|
39
|
-
e.persist
|
|
34
|
+
e.persist == null || e.persist();
|
|
40
35
|
this.setState(size, () => this.props.onResize && this.props.onResize(e, data));
|
|
41
36
|
} else {
|
|
42
37
|
this.setState(size);
|
|
@@ -60,24 +55,22 @@ class ResizableBox extends React.Component {
|
|
|
60
55
|
// If you use Resizable directly, you are responsible for updating the child component
|
|
61
56
|
// with a new width and height.
|
|
62
57
|
const _this$props = this.props,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
} = _this$props,
|
|
80
|
-
props = _objectWithoutProperties(_this$props, _excluded);
|
|
58
|
+
handle = _this$props.handle,
|
|
59
|
+
handleSize = _this$props.handleSize,
|
|
60
|
+
onResize = _this$props.onResize,
|
|
61
|
+
onResizeStart = _this$props.onResizeStart,
|
|
62
|
+
onResizeStop = _this$props.onResizeStop,
|
|
63
|
+
draggableOpts = _this$props.draggableOpts,
|
|
64
|
+
minConstraints = _this$props.minConstraints,
|
|
65
|
+
maxConstraints = _this$props.maxConstraints,
|
|
66
|
+
lockAspectRatio = _this$props.lockAspectRatio,
|
|
67
|
+
axis = _this$props.axis,
|
|
68
|
+
width = _this$props.width,
|
|
69
|
+
height = _this$props.height,
|
|
70
|
+
resizeHandles = _this$props.resizeHandles,
|
|
71
|
+
style = _this$props.style,
|
|
72
|
+
transformScale = _this$props.transformScale,
|
|
73
|
+
props = _objectWithoutPropertiesLoose(_this$props, _excluded);
|
|
81
74
|
return /*#__PURE__*/React.createElement(_Resizable.default, {
|
|
82
75
|
axis: axis,
|
|
83
76
|
draggableOpts: draggableOpts,
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { default as Resizable } from './Resizable';
|
|
2
|
+
export { default as ResizableBox } from './ResizableBox';
|
|
3
|
+
export type { Axis, DefaultProps, DragCallbackData, Props, ReactRef, ResizableBoxState, ResizableState, ResizeCallbackData, ResizeHandleAxis, } from './propTypes';
|
package/build/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.ResizableBox = exports.Resizable = void 0;
|
|
5
|
+
var _Resizable = _interopRequireDefault(require("./Resizable"));
|
|
6
|
+
exports.Resizable = _Resizable.default;
|
|
7
|
+
var _ResizableBox = _interopRequireDefault(require("./ResizableBox"));
|
|
8
|
+
exports.ResizableBox = _ResizableBox.default;
|
|
9
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type * as React from 'react';
|
|
2
|
+
import type { DraggableCore } from 'react-draggable';
|
|
3
|
+
export type ReactRef<T extends HTMLElement> = {
|
|
4
|
+
current: T | null;
|
|
5
|
+
};
|
|
6
|
+
export type Axis = 'both' | 'x' | 'y' | 'none';
|
|
7
|
+
export type ResizeHandleAxis = 's' | 'w' | 'e' | 'n' | 'sw' | 'nw' | 'se' | 'ne';
|
|
8
|
+
export type ResizableState = {};
|
|
9
|
+
export type ResizableBoxState = {
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
propsWidth: number;
|
|
13
|
+
propsHeight: number;
|
|
14
|
+
};
|
|
15
|
+
export type DragCallbackData = {
|
|
16
|
+
node: HTMLElement;
|
|
17
|
+
x: number;
|
|
18
|
+
y: number;
|
|
19
|
+
deltaX: number;
|
|
20
|
+
deltaY: number;
|
|
21
|
+
lastX: number;
|
|
22
|
+
lastY: number;
|
|
23
|
+
};
|
|
24
|
+
export type ResizeCallbackData = {
|
|
25
|
+
node: HTMLElement;
|
|
26
|
+
size: {
|
|
27
|
+
width: number;
|
|
28
|
+
height: number;
|
|
29
|
+
};
|
|
30
|
+
handle: ResizeHandleAxis;
|
|
31
|
+
};
|
|
32
|
+
export type DefaultProps = {
|
|
33
|
+
axis: Axis;
|
|
34
|
+
handleSize: [number, number];
|
|
35
|
+
lockAspectRatio: boolean;
|
|
36
|
+
minConstraints: [number, number];
|
|
37
|
+
maxConstraints: [number, number];
|
|
38
|
+
resizeHandles: ResizeHandleAxis[];
|
|
39
|
+
transformScale: number;
|
|
40
|
+
};
|
|
41
|
+
export type ResizeHandleFn = (resizeHandleAxis: ResizeHandleAxis, ref: React.RefObject<HTMLElement>) => React.ReactElement<any>;
|
|
42
|
+
export type Props = DefaultProps & {
|
|
43
|
+
children: React.ReactElement<any>;
|
|
44
|
+
className?: string | null;
|
|
45
|
+
draggableOpts?: Partial<React.ComponentProps<typeof DraggableCore>> | null;
|
|
46
|
+
height: number;
|
|
47
|
+
handle?: React.ReactElement<any> | ResizeHandleFn;
|
|
48
|
+
onResizeStop?: ((e: React.SyntheticEvent, data: ResizeCallbackData) => any) | null;
|
|
49
|
+
onResizeStart?: ((e: React.SyntheticEvent, data: ResizeCallbackData) => any) | null;
|
|
50
|
+
onResize?: ((e: React.SyntheticEvent, data: ResizeCallbackData) => any) | null;
|
|
51
|
+
width: number;
|
|
52
|
+
};
|
|
53
|
+
export declare const resizableProps: {
|
|
54
|
+
[key: string]: any;
|
|
55
|
+
};
|
package/build/propTypes.js
CHANGED
|
@@ -3,10 +3,9 @@
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
4
|
exports.resizableProps = void 0;
|
|
5
5
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
6
|
-
var _reactDraggable = require("react-draggable");
|
|
7
6
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
-
/* global Element */
|
|
9
7
|
// <Resizable>
|
|
8
|
+
|
|
10
9
|
const resizableProps = exports.resizableProps = {
|
|
11
10
|
/*
|
|
12
11
|
* Restricts resizing to a particular axis (default: 'both')
|
|
@@ -48,7 +47,7 @@ const resizableProps = exports.resizableProps = {
|
|
|
48
47
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
49
48
|
args[_key] = arguments[_key];
|
|
50
49
|
}
|
|
51
|
-
const
|
|
50
|
+
const props = args[0];
|
|
52
51
|
// Required if resizing height or both
|
|
53
52
|
if (props.axis === 'both' || props.axis === 'y') {
|
|
54
53
|
return _propTypes.default.number.isRequired(...args);
|
|
@@ -107,7 +106,7 @@ const resizableProps = exports.resizableProps = {
|
|
|
107
106
|
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
108
107
|
args[_key2] = arguments[_key2];
|
|
109
108
|
}
|
|
110
|
-
const
|
|
109
|
+
const props = args[0];
|
|
111
110
|
// Required if resizing width or both
|
|
112
111
|
if (props.axis === 'both' || props.axis === 'x') {
|
|
113
112
|
return _propTypes.default.number.isRequired(...args);
|
package/build/utils.d.ts
ADDED
package/build/utils.js
CHANGED
|
@@ -15,7 +15,7 @@ function cloneElement(element, props) {
|
|
|
15
15
|
props.style = _objectSpread(_objectSpread({}, element.props.style), props.style);
|
|
16
16
|
}
|
|
17
17
|
if (props.className && element.props.className) {
|
|
18
|
-
props.className =
|
|
18
|
+
props.className = element.props.className + " " + props.className;
|
|
19
19
|
}
|
|
20
20
|
return /*#__PURE__*/_react.default.cloneElement(element, props);
|
|
21
21
|
}
|
package/package.json
CHANGED
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-resizable",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "A component that is resizable with handles.",
|
|
5
5
|
"main": "index.js",
|
|
6
|
+
"types": "./build/index.d.ts",
|
|
6
7
|
"files": [
|
|
7
8
|
"build/",
|
|
8
9
|
"css/",
|
|
9
10
|
"index.js"
|
|
10
11
|
],
|
|
11
12
|
"scripts": {
|
|
12
|
-
"lint": "eslint lib/ __tests__/ setupTests
|
|
13
|
+
"lint": "eslint lib/ __tests__/ setupTests/",
|
|
14
|
+
"typecheck": "tsc --noEmit",
|
|
13
15
|
"test": "jest --coverage",
|
|
14
16
|
"unit": "jest --watch --verbose",
|
|
15
17
|
"build": "bash build.sh",
|
|
16
18
|
"build-example": "webpack",
|
|
17
19
|
"dev": "webpack serve --open",
|
|
18
20
|
"prepublishOnly": "npm run build",
|
|
19
|
-
"preversion": "npm run lint",
|
|
21
|
+
"preversion": "npm run lint && npm run typecheck",
|
|
20
22
|
"version": "git add CHANGELOG.md",
|
|
21
|
-
"postversion": "git push && git push --tags"
|
|
22
|
-
"flow": "flow"
|
|
23
|
+
"postversion": "git push && git push --tags"
|
|
23
24
|
},
|
|
24
25
|
"repository": {
|
|
25
26
|
"type": "git",
|
|
@@ -37,35 +38,41 @@
|
|
|
37
38
|
},
|
|
38
39
|
"homepage": "https://github.com/react-grid-layout/react-resizable",
|
|
39
40
|
"devDependencies": {
|
|
40
|
-
"@babel/cli": "^7.28.
|
|
41
|
-
"@babel/core": "^7.
|
|
42
|
-
"@babel/eslint-parser": "^7.28.5",
|
|
41
|
+
"@babel/cli": "^7.28.6",
|
|
42
|
+
"@babel/core": "^7.29.0",
|
|
43
43
|
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
|
44
44
|
"@babel/plugin-proposal-object-rest-spread": "^7.20.7",
|
|
45
|
-
"@babel/preset-env": "^7.
|
|
46
|
-
"@babel/preset-flow": "^7.27.1",
|
|
45
|
+
"@babel/preset-env": "^7.29.5",
|
|
47
46
|
"@babel/preset-react": "^7.28.5",
|
|
47
|
+
"@babel/preset-typescript": "^7.28.5",
|
|
48
|
+
"@eslint/js": "^9.39.4",
|
|
48
49
|
"@testing-library/dom": "^10.4.1",
|
|
49
50
|
"@testing-library/jest-dom": "^6.1.0",
|
|
50
|
-
"@testing-library/react": "^16.3.
|
|
51
|
+
"@testing-library/react": "^16.3.2",
|
|
51
52
|
"@testing-library/user-event": "^14.5.0",
|
|
52
|
-
"
|
|
53
|
+
"@types/jest": "^30.0.0",
|
|
54
|
+
"@types/prop-types": "^15.7.0",
|
|
55
|
+
"@types/react": "^19.2.0",
|
|
56
|
+
"@types/react-dom": "^19.2.0",
|
|
57
|
+
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
58
|
+
"@typescript-eslint/parser": "^8.0.0",
|
|
59
|
+
"babel-loader": "^10.1.1",
|
|
53
60
|
"cross-env": "^10.1.0",
|
|
54
|
-
"css-loader": "^7.1.
|
|
55
|
-
"eslint": "^9.39.
|
|
56
|
-
"eslint-plugin-jest": "^29.
|
|
61
|
+
"css-loader": "^7.1.4",
|
|
62
|
+
"eslint": "^9.39.4",
|
|
63
|
+
"eslint-plugin-jest": "^29.15.2",
|
|
57
64
|
"eslint-plugin-react": "^7.37.5",
|
|
58
|
-
"
|
|
59
|
-
"jest": "^30.
|
|
60
|
-
"
|
|
61
|
-
"lodash": "^4.17.20",
|
|
65
|
+
"jest": "^30.4.2",
|
|
66
|
+
"jest-environment-jsdom": "^30.4.1",
|
|
67
|
+
"lodash": "^4.18.1",
|
|
62
68
|
"pre-commit": "^1.1.2",
|
|
63
|
-
"react": "^19.2.
|
|
64
|
-
"react-dom": "^19.2.
|
|
69
|
+
"react": "^19.2.6",
|
|
70
|
+
"react-dom": "^19.2.6",
|
|
65
71
|
"style-loader": "^4.0.0",
|
|
66
|
-
"
|
|
67
|
-
"webpack
|
|
68
|
-
"webpack-
|
|
72
|
+
"typescript": "^5.6.0",
|
|
73
|
+
"webpack": "^5.106.2",
|
|
74
|
+
"webpack-cli": "^7.0.2",
|
|
75
|
+
"webpack-dev-server": "^5.2.4"
|
|
69
76
|
},
|
|
70
77
|
"dependencies": {
|
|
71
78
|
"prop-types": "15.x",
|
package/build/Resizable.js.flow
DELETED
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
import type {Node as ReactNode} from 'react';
|
|
4
|
-
import {DraggableCore} from 'react-draggable';
|
|
5
|
-
import {cloneElement} from './utils';
|
|
6
|
-
import {resizableProps} from "./propTypes";
|
|
7
|
-
import type {ResizeHandleAxis, DefaultProps, Props, ReactRef, DragCallbackData} from './propTypes';
|
|
8
|
-
|
|
9
|
-
// The base <Resizable> component.
|
|
10
|
-
// This component does not have state and relies on the parent to set its props based on callback data.
|
|
11
|
-
export default class Resizable extends React.Component<Props, void> {
|
|
12
|
-
static propTypes = resizableProps;
|
|
13
|
-
|
|
14
|
-
static defaultProps: DefaultProps = {
|
|
15
|
-
axis: 'both',
|
|
16
|
-
handleSize: [20, 20],
|
|
17
|
-
lockAspectRatio: false,
|
|
18
|
-
minConstraints: [20, 20],
|
|
19
|
-
maxConstraints: [Infinity, Infinity],
|
|
20
|
-
resizeHandles: ['se'],
|
|
21
|
-
transformScale: 1
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
handleRefs: {[key: ResizeHandleAxis]: ReactRef<HTMLElement>} = {};
|
|
25
|
-
lastHandleRect: ?ClientRect = null;
|
|
26
|
-
slack: ?[number, number] = null;
|
|
27
|
-
lastSize: ?{width: number, height: number} = null;
|
|
28
|
-
|
|
29
|
-
componentWillUnmount() {
|
|
30
|
-
this.resetData();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
resetData() {
|
|
34
|
-
this.lastHandleRect = this.slack = this.lastSize = null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Clamp width and height within provided constraints
|
|
38
|
-
runConstraints(width: number, height: number): [number, number] {
|
|
39
|
-
const {minConstraints, maxConstraints, lockAspectRatio} = this.props;
|
|
40
|
-
// short circuit
|
|
41
|
-
if (!minConstraints && !maxConstraints && !lockAspectRatio) return [width, height];
|
|
42
|
-
|
|
43
|
-
// If constraining to min and max, we need to also fit width and height to aspect ratio.
|
|
44
|
-
if (lockAspectRatio) {
|
|
45
|
-
const ratio = this.props.width / this.props.height;
|
|
46
|
-
const deltaW = width - this.props.width;
|
|
47
|
-
const deltaH = height - this.props.height;
|
|
48
|
-
|
|
49
|
-
// Find which coordinate was greater and should push the other toward it.
|
|
50
|
-
// E.g.:
|
|
51
|
-
// ratio = 1, deltaW = 10, deltaH = 5, deltaH should become 10.
|
|
52
|
-
// ratio = 2, deltaW = 10, deltaH = 6, deltaW should become 12.
|
|
53
|
-
if (Math.abs(deltaW) > Math.abs(deltaH * ratio)) {
|
|
54
|
-
height = width / ratio;
|
|
55
|
-
} else {
|
|
56
|
-
width = height * ratio;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const [oldW, oldH] = [width, height];
|
|
61
|
-
|
|
62
|
-
// Add slack to the values used to calculate bound position. This will ensure that if
|
|
63
|
-
// we start removing slack, the element won't react to it right away until it's been
|
|
64
|
-
// completely removed.
|
|
65
|
-
let [slackW, slackH] = this.slack || [0, 0];
|
|
66
|
-
width += slackW;
|
|
67
|
-
height += slackH;
|
|
68
|
-
|
|
69
|
-
if (minConstraints) {
|
|
70
|
-
width = Math.max(minConstraints[0], width);
|
|
71
|
-
height = Math.max(minConstraints[1], height);
|
|
72
|
-
}
|
|
73
|
-
if (maxConstraints) {
|
|
74
|
-
width = Math.min(maxConstraints[0], width);
|
|
75
|
-
height = Math.min(maxConstraints[1], height);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// If the width or height changed, we must have introduced some slack. Record it for the next iteration.
|
|
79
|
-
this.slack = [slackW + (oldW - width), slackH + (oldH - height)];
|
|
80
|
-
|
|
81
|
-
return [width, height];
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Wrapper around drag events to provide more useful data.
|
|
86
|
-
*
|
|
87
|
-
* @param {String} handlerName Handler name to wrap.
|
|
88
|
-
* @return {Function} Handler function.
|
|
89
|
-
*/
|
|
90
|
-
resizeHandler(handlerName: 'onResize' | 'onResizeStart' | 'onResizeStop', axis: ResizeHandleAxis): Function {
|
|
91
|
-
return (e: SyntheticEvent<>, {node, deltaX, deltaY}: DragCallbackData) => {
|
|
92
|
-
// Reset data in case it was left over somehow (should not be possible)
|
|
93
|
-
if (handlerName === 'onResizeStart') this.resetData();
|
|
94
|
-
|
|
95
|
-
// Axis restrictions
|
|
96
|
-
const canDragX = (this.props.axis === 'both' || this.props.axis === 'x') && axis !== 'n' && axis !== 's';
|
|
97
|
-
const canDragY = (this.props.axis === 'both' || this.props.axis === 'y') && axis !== 'e' && axis !== 'w';
|
|
98
|
-
// No dragging possible.
|
|
99
|
-
if (!canDragX && !canDragY) return;
|
|
100
|
-
|
|
101
|
-
// Decompose axis for later use
|
|
102
|
-
const axisV = axis[0];
|
|
103
|
-
const axisH = axis[axis.length - 1]; // intentionally not axis[1], so that this catches axis === 'w' for example
|
|
104
|
-
|
|
105
|
-
// Track the element being dragged to account for changes in position.
|
|
106
|
-
// If a handle's position is changed between callbacks, we need to factor this in to the next callback.
|
|
107
|
-
// Failure to do so will cause the element to "skip" when resized upwards or leftwards.
|
|
108
|
-
const handleRect = node.getBoundingClientRect();
|
|
109
|
-
if (this.lastHandleRect != null) {
|
|
110
|
-
// If the handle has repositioned on either axis since last render,
|
|
111
|
-
// we need to increase our callback values by this much.
|
|
112
|
-
// Only checking 'n', 'w' since resizing by 's', 'w' won't affect the overall position on page,
|
|
113
|
-
if (axisH === 'w') {
|
|
114
|
-
const deltaLeftSinceLast = handleRect.left - this.lastHandleRect.left;
|
|
115
|
-
deltaX += deltaLeftSinceLast;
|
|
116
|
-
}
|
|
117
|
-
if (axisV === 'n') {
|
|
118
|
-
const deltaTopSinceLast = handleRect.top - this.lastHandleRect.top;
|
|
119
|
-
deltaY += deltaTopSinceLast;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
// Storage of last rect so we know how much it has really moved.
|
|
123
|
-
this.lastHandleRect = handleRect;
|
|
124
|
-
|
|
125
|
-
// Reverse delta if using top or left drag handles.
|
|
126
|
-
if (axisH === 'w') deltaX = -deltaX;
|
|
127
|
-
if (axisV === 'n') deltaY = -deltaY;
|
|
128
|
-
|
|
129
|
-
// Update w/h by the deltas. Also factor in transformScale.
|
|
130
|
-
let width = this.props.width + (canDragX ? deltaX / this.props.transformScale : 0);
|
|
131
|
-
let height = this.props.height + (canDragY ? deltaY / this.props.transformScale : 0);
|
|
132
|
-
|
|
133
|
-
// Run user-provided constraints.
|
|
134
|
-
[width, height] = this.runConstraints(width, height);
|
|
135
|
-
|
|
136
|
-
// For onResizeStop, use the last size from onResize rather than recalculating.
|
|
137
|
-
// This avoids issues where props.width/height are stale due to React's batched updates.
|
|
138
|
-
if (handlerName === 'onResizeStop' && this.lastSize) {
|
|
139
|
-
({width, height} = this.lastSize);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const dimensionsChanged = width !== this.props.width || height !== this.props.height;
|
|
143
|
-
|
|
144
|
-
// Store the size for use in onResizeStop. We do this after the onResizeStop check
|
|
145
|
-
// above so we don't overwrite the stored value with a potentially stale calculation.
|
|
146
|
-
if (handlerName !== 'onResizeStop') {
|
|
147
|
-
this.lastSize = {width, height};
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Call user-supplied callback if present.
|
|
151
|
-
const cb = typeof this.props[handlerName] === 'function' ? this.props[handlerName] : null;
|
|
152
|
-
// Don't call 'onResize' if dimensions haven't changed.
|
|
153
|
-
const shouldSkipCb = handlerName === 'onResize' && !dimensionsChanged;
|
|
154
|
-
if (cb && !shouldSkipCb) {
|
|
155
|
-
e.persist?.();
|
|
156
|
-
cb(e, {node, size: {width, height}, handle: axis});
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Reset internal data
|
|
160
|
-
if (handlerName === 'onResizeStop') this.resetData();
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Render a resize handle given an axis & DOM ref. Ref *must* be attached for
|
|
165
|
-
// the underlying draggable library to work properly.
|
|
166
|
-
renderResizeHandle(handleAxis: ResizeHandleAxis, ref: ReactRef<HTMLElement>): ReactNode {
|
|
167
|
-
const {handle} = this.props;
|
|
168
|
-
// No handle provided, make the default
|
|
169
|
-
if (!handle) {
|
|
170
|
-
return <span className={`react-resizable-handle react-resizable-handle-${handleAxis}`} ref={ref} />;
|
|
171
|
-
}
|
|
172
|
-
// Handle is a function, such as:
|
|
173
|
-
// `handle={(handleAxis) => <span className={...} />}`
|
|
174
|
-
if (typeof handle === 'function') {
|
|
175
|
-
return handle(handleAxis, ref);
|
|
176
|
-
}
|
|
177
|
-
// Handle is a React component (composite or DOM).
|
|
178
|
-
const isDOMElement = typeof handle.type === 'string';
|
|
179
|
-
const props = {
|
|
180
|
-
ref,
|
|
181
|
-
// Add `handleAxis` prop iff this is not a DOM element,
|
|
182
|
-
// otherwise we'll get an unknown property warning
|
|
183
|
-
...(isDOMElement ? {} : {handleAxis})
|
|
184
|
-
};
|
|
185
|
-
return React.cloneElement(handle, props);
|
|
186
|
-
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
render(): ReactNode {
|
|
190
|
-
// Pass along only props not meant for the `<Resizable>`.`
|
|
191
|
-
// eslint-disable-next-line no-unused-vars
|
|
192
|
-
const {children, className, draggableOpts, width, height, handle, handleSize,
|
|
193
|
-
lockAspectRatio, axis, minConstraints, maxConstraints, onResize,
|
|
194
|
-
onResizeStop, onResizeStart, resizeHandles, transformScale, ...p} = this.props;
|
|
195
|
-
|
|
196
|
-
// What we're doing here is getting the child of this element, and cloning it with this element's props.
|
|
197
|
-
// We are then defining its children as:
|
|
198
|
-
// 1. Its original children (resizable's child's children), and
|
|
199
|
-
// 2. One or more draggable handles.
|
|
200
|
-
return cloneElement(children, {
|
|
201
|
-
...p,
|
|
202
|
-
className: `${className ? `${className} ` : ''}react-resizable`,
|
|
203
|
-
children: [
|
|
204
|
-
...React.Children.toArray(children.props.children),
|
|
205
|
-
...resizeHandles.map((handleAxis) => {
|
|
206
|
-
// Create a ref to the handle so that `<DraggableCore>` doesn't have to use ReactDOM.findDOMNode().
|
|
207
|
-
const ref = (this.handleRefs[handleAxis]) ?? (this.handleRefs[handleAxis] = React.createRef());
|
|
208
|
-
return (
|
|
209
|
-
<DraggableCore
|
|
210
|
-
{...draggableOpts}
|
|
211
|
-
nodeRef={ref}
|
|
212
|
-
key={`resizableHandle-${handleAxis}`}
|
|
213
|
-
onStop={this.resizeHandler('onResizeStop', handleAxis)}
|
|
214
|
-
onStart={this.resizeHandler('onResizeStart', handleAxis)}
|
|
215
|
-
onDrag={this.resizeHandler('onResize', handleAxis)}
|
|
216
|
-
>
|
|
217
|
-
{this.renderResizeHandle(handleAxis, ref)}
|
|
218
|
-
</DraggableCore>
|
|
219
|
-
);
|
|
220
|
-
})
|
|
221
|
-
]
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
}
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
import type {Node as ReactNode, Element as ReactElement} from 'react';
|
|
4
|
-
import PropTypes from 'prop-types';
|
|
5
|
-
|
|
6
|
-
import Resizable from './Resizable';
|
|
7
|
-
import {resizableProps} from "./propTypes";
|
|
8
|
-
import type {ResizeCallbackData, ResizableBoxState} from './propTypes';
|
|
9
|
-
|
|
10
|
-
// ElementConfig gives us an object type where all items present in `defaultProps` are made optional.
|
|
11
|
-
// <ResizableBox> does not have defaultProps, so we can use this type to tell Flow that we don't
|
|
12
|
-
// care about that and will handle it in <Resizable> instead.
|
|
13
|
-
// A <ResizableBox> can also have a `style` property.
|
|
14
|
-
type ResizableBoxProps = {|...React.ElementConfig<typeof Resizable>, style?: Object, children?: ReactElement<any>|};
|
|
15
|
-
|
|
16
|
-
export default class ResizableBox extends React.Component<ResizableBoxProps, ResizableBoxState> {
|
|
17
|
-
|
|
18
|
-
// PropTypes are identical to <Resizable>, except that children are not strictly required to be present.
|
|
19
|
-
static propTypes = {
|
|
20
|
-
...resizableProps,
|
|
21
|
-
children: PropTypes.element,
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
state: ResizableBoxState = {
|
|
25
|
-
width: this.props.width,
|
|
26
|
-
height: this.props.height,
|
|
27
|
-
propsWidth: this.props.width,
|
|
28
|
-
propsHeight: this.props.height,
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
static getDerivedStateFromProps(props: ResizableBoxProps, state: ResizableBoxState): ?ResizableBoxState {
|
|
32
|
-
// If parent changes height/width, set that in our state.
|
|
33
|
-
if (state.propsWidth !== props.width || state.propsHeight !== props.height) {
|
|
34
|
-
return {
|
|
35
|
-
width: props.width,
|
|
36
|
-
height: props.height,
|
|
37
|
-
propsWidth: props.width,
|
|
38
|
-
propsHeight: props.height,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
return null;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
onResize: (e: SyntheticEvent<>, data: ResizeCallbackData) => void = (e, data) => {
|
|
45
|
-
const {size} = data;
|
|
46
|
-
if (this.props.onResize) {
|
|
47
|
-
e.persist?.();
|
|
48
|
-
this.setState(size, () => this.props.onResize && this.props.onResize(e, data));
|
|
49
|
-
} else {
|
|
50
|
-
this.setState(size);
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
render(): ReactNode {
|
|
55
|
-
// Basic wrapper around a Resizable instance.
|
|
56
|
-
// If you use Resizable directly, you are responsible for updating the child component
|
|
57
|
-
// with a new width and height.
|
|
58
|
-
const {
|
|
59
|
-
handle,
|
|
60
|
-
handleSize,
|
|
61
|
-
onResize,
|
|
62
|
-
onResizeStart,
|
|
63
|
-
onResizeStop,
|
|
64
|
-
draggableOpts,
|
|
65
|
-
minConstraints,
|
|
66
|
-
maxConstraints,
|
|
67
|
-
lockAspectRatio,
|
|
68
|
-
axis,
|
|
69
|
-
width,
|
|
70
|
-
height,
|
|
71
|
-
resizeHandles,
|
|
72
|
-
style,
|
|
73
|
-
transformScale,
|
|
74
|
-
...props
|
|
75
|
-
} = this.props;
|
|
76
|
-
|
|
77
|
-
return (
|
|
78
|
-
<Resizable
|
|
79
|
-
axis={axis}
|
|
80
|
-
draggableOpts={draggableOpts}
|
|
81
|
-
handle={handle}
|
|
82
|
-
handleSize={handleSize}
|
|
83
|
-
height={this.state.height}
|
|
84
|
-
lockAspectRatio={lockAspectRatio}
|
|
85
|
-
maxConstraints={maxConstraints}
|
|
86
|
-
minConstraints={minConstraints}
|
|
87
|
-
onResizeStart={onResizeStart}
|
|
88
|
-
onResize={this.onResize}
|
|
89
|
-
onResizeStop={onResizeStop}
|
|
90
|
-
resizeHandles={resizeHandles}
|
|
91
|
-
transformScale={transformScale}
|
|
92
|
-
width={this.state.width}
|
|
93
|
-
>
|
|
94
|
-
<div {...props} style={{...style, width: this.state.width + 'px', height: this.state.height + 'px'}} />
|
|
95
|
-
</Resizable>
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
}
|
package/build/propTypes.js.flow
DELETED
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
/* global Element */
|
|
3
|
-
import PropTypes from 'prop-types';
|
|
4
|
-
import {DraggableCore} from "react-draggable";
|
|
5
|
-
import type {Element as ReactElement, ElementConfig} from 'react';
|
|
6
|
-
|
|
7
|
-
export type ReactRef<T: HTMLElement> = {
|
|
8
|
-
current: T | null
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export type Axis = 'both' | 'x' | 'y' | 'none';
|
|
12
|
-
export type ResizeHandleAxis = 's' | 'w' | 'e' | 'n' | 'sw' | 'nw' | 'se' | 'ne';
|
|
13
|
-
export type ResizableState = void;
|
|
14
|
-
export type ResizableBoxState = {
|
|
15
|
-
width: number, height: number,
|
|
16
|
-
propsWidth: number, propsHeight: number
|
|
17
|
-
};
|
|
18
|
-
export type DragCallbackData = {
|
|
19
|
-
node: HTMLElement,
|
|
20
|
-
x: number, y: number,
|
|
21
|
-
deltaX: number, deltaY: number,
|
|
22
|
-
lastX: number, lastY: number
|
|
23
|
-
};
|
|
24
|
-
export type ResizeCallbackData = {
|
|
25
|
-
node: HTMLElement,
|
|
26
|
-
size: {width: number, height: number},
|
|
27
|
-
handle: ResizeHandleAxis
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
// <Resizable>
|
|
31
|
-
export type DefaultProps = {
|
|
32
|
-
axis: Axis,
|
|
33
|
-
handleSize: [number, number],
|
|
34
|
-
lockAspectRatio: boolean,
|
|
35
|
-
minConstraints: [number, number],
|
|
36
|
-
maxConstraints: [number, number],
|
|
37
|
-
resizeHandles: ResizeHandleAxis[],
|
|
38
|
-
transformScale: number,
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export type Props = {
|
|
42
|
-
...DefaultProps,
|
|
43
|
-
children: ReactElement<any>,
|
|
44
|
-
className?: ?string,
|
|
45
|
-
draggableOpts?: ?ElementConfig<typeof DraggableCore>,
|
|
46
|
-
height: number,
|
|
47
|
-
handle?: ReactElement<any> | (resizeHandleAxis: ResizeHandleAxis, ref: ReactRef<HTMLElement>) => ReactElement<any>,
|
|
48
|
-
onResizeStop?: ?(e: SyntheticEvent<>, data: ResizeCallbackData) => any,
|
|
49
|
-
onResizeStart?: ?(e: SyntheticEvent<>, data: ResizeCallbackData) => any,
|
|
50
|
-
onResize?: ?(e: SyntheticEvent<>, data: ResizeCallbackData) => any,
|
|
51
|
-
width: number,
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
export const resizableProps: Object = {
|
|
57
|
-
/*
|
|
58
|
-
* Restricts resizing to a particular axis (default: 'both')
|
|
59
|
-
* 'both' - allows resizing by width or height
|
|
60
|
-
* 'x' - only allows the width to be changed
|
|
61
|
-
* 'y' - only allows the height to be changed
|
|
62
|
-
* 'none' - disables resizing altogether
|
|
63
|
-
* */
|
|
64
|
-
axis: PropTypes.oneOf(['both', 'x', 'y', 'none']),
|
|
65
|
-
className: PropTypes.string,
|
|
66
|
-
/*
|
|
67
|
-
* Require that one and only one child be present.
|
|
68
|
-
* */
|
|
69
|
-
children: PropTypes.element.isRequired,
|
|
70
|
-
/*
|
|
71
|
-
* These will be passed wholesale to react-draggable's DraggableCore
|
|
72
|
-
* */
|
|
73
|
-
draggableOpts: PropTypes.shape({
|
|
74
|
-
allowAnyClick: PropTypes.bool,
|
|
75
|
-
cancel: PropTypes.string,
|
|
76
|
-
children: PropTypes.node,
|
|
77
|
-
disabled: PropTypes.bool,
|
|
78
|
-
enableUserSelectHack: PropTypes.bool,
|
|
79
|
-
// #251: Check for Element to support SSR environments where DOM globals don't exist
|
|
80
|
-
offsetParent: typeof Element !== 'undefined' ? PropTypes.instanceOf(Element) : PropTypes.any,
|
|
81
|
-
grid: PropTypes.arrayOf(PropTypes.number),
|
|
82
|
-
handle: PropTypes.string,
|
|
83
|
-
nodeRef: PropTypes.object,
|
|
84
|
-
onStart: PropTypes.func,
|
|
85
|
-
onDrag: PropTypes.func,
|
|
86
|
-
onStop: PropTypes.func,
|
|
87
|
-
onMouseDown: PropTypes.func,
|
|
88
|
-
scale: PropTypes.number,
|
|
89
|
-
}),
|
|
90
|
-
/*
|
|
91
|
-
* Initial height
|
|
92
|
-
* */
|
|
93
|
-
height: (...args) => {
|
|
94
|
-
const [props] = args;
|
|
95
|
-
// Required if resizing height or both
|
|
96
|
-
if (props.axis === 'both' || props.axis === 'y') {
|
|
97
|
-
return PropTypes.number.isRequired(...args);
|
|
98
|
-
}
|
|
99
|
-
return PropTypes.number(...args);
|
|
100
|
-
},
|
|
101
|
-
/*
|
|
102
|
-
* Customize cursor resize handle
|
|
103
|
-
* */
|
|
104
|
-
handle: PropTypes.oneOfType([
|
|
105
|
-
PropTypes.node,
|
|
106
|
-
PropTypes.func
|
|
107
|
-
]),
|
|
108
|
-
/*
|
|
109
|
-
* If you change this, be sure to update your css
|
|
110
|
-
* */
|
|
111
|
-
handleSize: PropTypes.arrayOf(PropTypes.number),
|
|
112
|
-
lockAspectRatio: PropTypes.bool,
|
|
113
|
-
/*
|
|
114
|
-
* Max X & Y measure
|
|
115
|
-
* */
|
|
116
|
-
maxConstraints: PropTypes.arrayOf(PropTypes.number),
|
|
117
|
-
/*
|
|
118
|
-
* Min X & Y measure
|
|
119
|
-
* */
|
|
120
|
-
minConstraints: PropTypes.arrayOf(PropTypes.number),
|
|
121
|
-
/*
|
|
122
|
-
* Called on stop resize event
|
|
123
|
-
* */
|
|
124
|
-
onResizeStop: PropTypes.func,
|
|
125
|
-
/*
|
|
126
|
-
* Called on start resize event
|
|
127
|
-
* */
|
|
128
|
-
onResizeStart: PropTypes.func,
|
|
129
|
-
/*
|
|
130
|
-
* Called on resize event
|
|
131
|
-
* */
|
|
132
|
-
onResize: PropTypes.func,
|
|
133
|
-
/*
|
|
134
|
-
* Defines which resize handles should be rendered (default: 'se')
|
|
135
|
-
* 's' - South handle (bottom-center)
|
|
136
|
-
* 'w' - West handle (left-center)
|
|
137
|
-
* 'e' - East handle (right-center)
|
|
138
|
-
* 'n' - North handle (top-center)
|
|
139
|
-
* 'sw' - Southwest handle (bottom-left)
|
|
140
|
-
* 'nw' - Northwest handle (top-left)
|
|
141
|
-
* 'se' - Southeast handle (bottom-right)
|
|
142
|
-
* 'ne' - Northeast handle (top-center)
|
|
143
|
-
* */
|
|
144
|
-
resizeHandles: PropTypes.arrayOf(PropTypes.oneOf(['s', 'w', 'e', 'n', 'sw', 'nw', 'se', 'ne'])),
|
|
145
|
-
|
|
146
|
-
/*
|
|
147
|
-
* If `transform: scale(n)` is set on the parent, this should be set to `n`.
|
|
148
|
-
* */
|
|
149
|
-
transformScale: PropTypes.number,
|
|
150
|
-
/*
|
|
151
|
-
* Initial width
|
|
152
|
-
*/
|
|
153
|
-
width: (...args) => {
|
|
154
|
-
const [props] = args;
|
|
155
|
-
// Required if resizing width or both
|
|
156
|
-
if (props.axis === 'both' || props.axis === 'x') {
|
|
157
|
-
return PropTypes.number.isRequired(...args);
|
|
158
|
-
}
|
|
159
|
-
return PropTypes.number(...args);
|
|
160
|
-
},
|
|
161
|
-
};
|
package/build/utils.js.flow
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
import React from 'react';
|
|
3
|
-
import type {Element as ReactElement} from 'react';
|
|
4
|
-
|
|
5
|
-
// React.addons.cloneWithProps look-alike that merges style & className.
|
|
6
|
-
export function cloneElement(element: ReactElement<any>, props: Object): ReactElement<any> {
|
|
7
|
-
if (props.style && element.props.style) {
|
|
8
|
-
props.style = {...element.props.style, ...props.style};
|
|
9
|
-
}
|
|
10
|
-
if (props.className && element.props.className) {
|
|
11
|
-
props.className = `${element.props.className} ${props.className}`;
|
|
12
|
-
}
|
|
13
|
-
return React.cloneElement(element, props);
|
|
14
|
-
}
|