@douyinfe/semi-foundation 2.67.2 → 2.68.0-beta.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.
Files changed (44) hide show
  1. package/datePicker/foundation.ts +1 -1
  2. package/lib/cjs/datePicker/foundation.d.ts +1 -1
  3. package/lib/cjs/resizable/constants.d.ts +5 -0
  4. package/lib/cjs/resizable/constants.js +11 -0
  5. package/lib/cjs/resizable/foundation.d.ts +4 -0
  6. package/lib/cjs/resizable/foundation.js +37 -0
  7. package/lib/cjs/resizable/group/index.d.ts +50 -0
  8. package/lib/cjs/resizable/group/index.js +271 -0
  9. package/lib/cjs/resizable/groupConstants.d.ts +16 -0
  10. package/lib/cjs/resizable/groupConstants.js +25 -0
  11. package/lib/cjs/resizable/resizable.css +34 -0
  12. package/lib/cjs/resizable/resizable.scss +39 -0
  13. package/lib/cjs/resizable/single/index.d.ts +70 -0
  14. package/lib/cjs/resizable/single/index.js +574 -0
  15. package/lib/cjs/resizable/singleConstants.d.ts +105 -0
  16. package/lib/cjs/resizable/singleConstants.js +67 -0
  17. package/lib/cjs/resizable/utils.d.ts +20 -0
  18. package/lib/cjs/resizable/utils.js +142 -0
  19. package/lib/es/datePicker/foundation.d.ts +1 -1
  20. package/lib/es/resizable/constants.d.ts +5 -0
  21. package/lib/es/resizable/constants.js +6 -0
  22. package/lib/es/resizable/foundation.d.ts +4 -0
  23. package/lib/es/resizable/foundation.js +4 -0
  24. package/lib/es/resizable/group/index.d.ts +50 -0
  25. package/lib/es/resizable/group/index.js +262 -0
  26. package/lib/es/resizable/groupConstants.d.ts +16 -0
  27. package/lib/es/resizable/groupConstants.js +19 -0
  28. package/lib/es/resizable/resizable.css +34 -0
  29. package/lib/es/resizable/resizable.scss +39 -0
  30. package/lib/es/resizable/single/index.d.ts +70 -0
  31. package/lib/es/resizable/single/index.js +565 -0
  32. package/lib/es/resizable/singleConstants.d.ts +105 -0
  33. package/lib/es/resizable/singleConstants.js +61 -0
  34. package/lib/es/resizable/utils.d.ts +20 -0
  35. package/lib/es/resizable/utils.js +124 -0
  36. package/package.json +3 -3
  37. package/resizable/constants.ts +13 -0
  38. package/resizable/foundation.ts +31 -0
  39. package/resizable/group/index.ts +293 -0
  40. package/resizable/groupConstants.ts +25 -0
  41. package/resizable/resizable.scss +39 -0
  42. package/resizable/single/index.ts +629 -0
  43. package/resizable/singleConstants.ts +127 -0
  44. package/resizable/utils.ts +145 -0
@@ -0,0 +1,39 @@
1
+ $module: #{$prefix}-resizable;
2
+
3
+ .#{$module} {
4
+ &-resizable {
5
+ position: relative;
6
+ box-sizing: border-box;
7
+ flex-shrink: 0;
8
+ }
9
+
10
+ &-resizableHandler {
11
+ position: absolute;
12
+ user-select: none;
13
+ z-index: $z-resizable_handler;
14
+ }
15
+
16
+ &-group {
17
+ display: flex;
18
+ position: relative;
19
+ box-sizing: border-box;
20
+ height: 100%;
21
+ width: 100%;
22
+ }
23
+
24
+ &-item {
25
+ position: relative;
26
+ box-sizing: border-box;
27
+ flex-shrink: 0;
28
+ }
29
+
30
+ &-handler {
31
+ user-select: none;
32
+ z-index: $z-resizable_handler;
33
+ display: flex;
34
+ align-items: center;
35
+ justify-content: center;
36
+ background-color: var(--semi-color-fill-0);
37
+ opacity: 1;
38
+ }
39
+ }
@@ -0,0 +1,70 @@
1
+ import BaseFoundation, { DefaultAdapter } from '../../base/foundation';
2
+ import { Size, NumberSize, Direction } from "../singleConstants";
3
+ export interface ResizableHandlerAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
4
+ registerEvent: () => void;
5
+ unregisterEvent: () => void;
6
+ }
7
+ export declare class ResizableHandlerFoundation<P = Record<string, any>, S = Record<string, any>> extends BaseFoundation<ResizableHandlerAdapter<P, S>, P, S> {
8
+ constructor(adapter: ResizableHandlerAdapter<P, S>);
9
+ init(): void;
10
+ onMouseDown: (e: MouseEvent) => void;
11
+ destroy(): void;
12
+ }
13
+ export interface ResizableAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
14
+ getResizable: () => HTMLDivElement | null;
15
+ registerEvent: () => void;
16
+ unregisterEvent: () => void;
17
+ }
18
+ export declare class ResizableFoundation<P = Record<string, any>, S = Record<string, any>> extends BaseFoundation<ResizableAdapter<P, S>, P, S> {
19
+ constructor(adapter: ResizableAdapter<P, S>);
20
+ init(): void;
21
+ flexDirection?: 'row' | 'column';
22
+ lockAspectRatio: number;
23
+ resizable: HTMLElement | null;
24
+ parentLeft: number;
25
+ parentTop: number;
26
+ boundaryLeft: number;
27
+ boundaryRight: number;
28
+ boundaryTop: number;
29
+ boundaryBottom: number;
30
+ targetLeft: number;
31
+ targetTop: number;
32
+ get parent(): HTMLElement | null;
33
+ get window(): Window | null;
34
+ get propSize(): Size;
35
+ get size(): NumberSize;
36
+ get sizeStyle(): {
37
+ width: string;
38
+ height: string;
39
+ };
40
+ getParentSize(): {
41
+ width: number;
42
+ height: number;
43
+ };
44
+ registerEvents(): void;
45
+ unregisterEvents(): void;
46
+ getCssPropertySize(newSize: number | string, property: 'width' | 'height'): number | string;
47
+ calBoundaryMax(maxWidth?: number, maxHeight?: number): {
48
+ maxWidth: number;
49
+ maxHeight: number;
50
+ };
51
+ calDirectionSize(clientX: number, clientY: number): {
52
+ newWidth: any;
53
+ newHeight: any;
54
+ };
55
+ calAspectRatioSize(newWidth: number, newHeight: number, max: {
56
+ width?: number;
57
+ height?: number;
58
+ }, min: {
59
+ width?: number;
60
+ height?: number;
61
+ }): {
62
+ newWidth: number;
63
+ newHeight: number;
64
+ };
65
+ setBoundary(): void;
66
+ onResizeStart: (e: MouseEvent, direction: Direction) => void;
67
+ onMouseMove: (event: MouseEvent) => void;
68
+ onMouseUp: (event: MouseEvent) => void;
69
+ destroy(): void;
70
+ }
@@ -0,0 +1,565 @@
1
+ import BaseFoundation from '../../base/foundation';
2
+ import { DEFAULT_SIZE } from "../singleConstants";
3
+ import { getStringSize, getNumberSize, has, calculateNewMax, findNextSnap, snap, clamp } from "../utils";
4
+ export class ResizableHandlerFoundation extends BaseFoundation {
5
+ constructor(adapter) {
6
+ super(Object.assign({}, adapter));
7
+ this.onMouseDown = e => {
8
+ this.getProp('onResizeStart')(e, this.getProp('direction'));
9
+ };
10
+ }
11
+ init() {
12
+ this._adapter.registerEvent();
13
+ }
14
+ destroy() {
15
+ this._adapter.unregisterEvent();
16
+ }
17
+ }
18
+ export class ResizableFoundation extends BaseFoundation {
19
+ constructor(adapter) {
20
+ super(Object.assign({}, adapter));
21
+ this.lockAspectRatio = 1;
22
+ this.resizable = null;
23
+ this.parentLeft = 0;
24
+ this.parentTop = 0;
25
+ this.boundaryLeft = 0;
26
+ this.boundaryRight = 0;
27
+ this.boundaryTop = 0;
28
+ this.boundaryBottom = 0;
29
+ this.targetLeft = 0;
30
+ this.targetTop = 0;
31
+ this.onResizeStart = (e, direction) => {
32
+ this.resizable = this._adapter.getResizable();
33
+ if (!this.resizable || !this.window) {
34
+ return;
35
+ }
36
+ const {
37
+ clientX,
38
+ clientY
39
+ } = e;
40
+ const props = this.getProps();
41
+ const states = this.getStates();
42
+ // Call onResizeStart callback if defined
43
+ if (props.onResizeStart) {
44
+ const shouldContinue = props.onResizeStart(e, direction);
45
+ if (shouldContinue === false) {
46
+ return;
47
+ }
48
+ }
49
+ // Update state with new size if defined
50
+ const {
51
+ size
52
+ } = props;
53
+ if (size) {
54
+ const {
55
+ height,
56
+ width
57
+ } = size;
58
+ const {
59
+ height: currentHeight,
60
+ width: currentWidth
61
+ } = states;
62
+ if (height !== undefined && height !== currentHeight) {
63
+ this.setState({
64
+ height
65
+ });
66
+ }
67
+ if (width !== undefined && width !== currentWidth) {
68
+ this.setState({
69
+ width
70
+ });
71
+ }
72
+ }
73
+ // Handle aspect ratio locking
74
+ this.lockAspectRatio = typeof props.lockAspectRatio === 'number' ? props.lockAspectRatio : this.size.width / this.size.height;
75
+ // Determine flexBasis if applicable
76
+ let flexBasis;
77
+ const computedStyle = this.window.getComputedStyle(this.resizable);
78
+ if (computedStyle.flexBasis !== 'auto') {
79
+ const parent = this.parent;
80
+ if (parent) {
81
+ const parentStyle = this.window.getComputedStyle(parent);
82
+ this.flexDirection = parentStyle.flexDirection.startsWith('row') ? 'row' : 'column';
83
+ flexBasis = computedStyle.flexBasis;
84
+ }
85
+ }
86
+ // Set bounding rectangle and register events
87
+ this.setBoundary();
88
+ this.registerEvents();
89
+ // Update state with initial resize values
90
+ const state = {
91
+ original: {
92
+ x: clientX,
93
+ y: clientY,
94
+ width: this.size.width,
95
+ height: this.size.height
96
+ },
97
+ isResizing: true,
98
+ backgroundStyle: Object.assign(Object.assign({}, states.backgroundStyle), {
99
+ cursor: this.window.getComputedStyle(e.target).cursor || 'auto'
100
+ }),
101
+ direction,
102
+ flexBasis
103
+ };
104
+ this.setState(state);
105
+ };
106
+ this.onMouseMove = event => {
107
+ var _a, _b;
108
+ const states = this.getStates();
109
+ const props = this.getProps();
110
+ if (!states.isResizing || !this.resizable || !this.window) {
111
+ return;
112
+ }
113
+ const {
114
+ clientX,
115
+ clientY
116
+ } = event;
117
+ const {
118
+ direction,
119
+ original,
120
+ width,
121
+ height
122
+ } = states;
123
+ const parentSize = this.getParentSize();
124
+ let {
125
+ maxWidth,
126
+ maxHeight,
127
+ minWidth,
128
+ minHeight
129
+ } = props;
130
+ // Calculate max and min dimensions
131
+ const maxBounds = calculateNewMax(parentSize, this.window.innerWidth, this.window.innerHeight, maxWidth, maxHeight, minWidth, minHeight);
132
+ maxWidth = maxBounds.maxWidth;
133
+ maxHeight = maxBounds.maxHeight;
134
+ minWidth = maxBounds.minWidth;
135
+ minHeight = maxBounds.minHeight;
136
+ // Calculate new size based on direction
137
+ let {
138
+ newWidth,
139
+ newHeight
140
+ } = this.calDirectionSize(clientX, clientY);
141
+ // Apply boundary constraints
142
+ const boundaryMax = this.calBoundaryMax(maxWidth, maxHeight);
143
+ newWidth = getNumberSize(newWidth, parentSize.width, this.window.innerWidth, this.window.innerHeight);
144
+ newHeight = getNumberSize(newHeight, parentSize.height, this.window.innerWidth, this.window.innerHeight);
145
+ // Apply snapping
146
+ if (props.snap) {
147
+ if (props.snap.x) {
148
+ newWidth = findNextSnap(newWidth, props.snap.x, props.snapGap);
149
+ }
150
+ if (props.snap.y) {
151
+ newHeight = findNextSnap(newHeight, props.snap.y, props.snapGap);
152
+ }
153
+ }
154
+ // Adjust size based on aspect ratio
155
+ const sizeFromAspectRatio = this.calAspectRatioSize(newWidth, newHeight, {
156
+ width: boundaryMax.maxWidth,
157
+ height: boundaryMax.maxHeight
158
+ }, {
159
+ width: minWidth,
160
+ height: minHeight
161
+ });
162
+ newWidth = sizeFromAspectRatio.newWidth;
163
+ newHeight = sizeFromAspectRatio.newHeight;
164
+ // Apply grid snapping if defined
165
+ if (props.grid) {
166
+ const [gridW, gridH] = Array.isArray(props.grid) ? props.grid : [props.grid, props.grid];
167
+ const gap = props.snapGap || 0;
168
+ const newGridWidth = snap(newWidth, gridW);
169
+ const newGridHeight = snap(newHeight, gridH);
170
+ newWidth = gap === 0 || Math.abs(newGridWidth - newWidth) <= gap ? newGridWidth : newWidth;
171
+ newHeight = gap === 0 || Math.abs(newGridHeight - newHeight) <= gap ? newGridHeight : newHeight;
172
+ }
173
+ // Convert width and height to CSS units if needed
174
+ const convertToCssUnit = (size, originalSize, unit) => {
175
+ if (unit.endsWith('%')) {
176
+ return `${size / originalSize * 100}%`;
177
+ } else if (unit.endsWith('vw')) {
178
+ return `${size / this.window.innerWidth * 100}vw`;
179
+ } else if (unit.endsWith('vh')) {
180
+ return `${size / this.window.innerHeight * 100}vh`;
181
+ }
182
+ return size;
183
+ };
184
+ if (typeof width === 'string') {
185
+ newWidth = convertToCssUnit(newWidth, parentSize.width, width || '');
186
+ }
187
+ if (typeof height === 'string') {
188
+ newHeight = convertToCssUnit(newHeight, parentSize.height, height || '');
189
+ }
190
+ // Create new state
191
+ const newState = {
192
+ width: this.getCssPropertySize(newWidth, 'width'),
193
+ height: this.getCssPropertySize(newHeight, 'height')
194
+ };
195
+ if (this.flexDirection === 'row') {
196
+ newState.flexBasis = newState.width;
197
+ } else if (this.flexDirection === 'column') {
198
+ newState.flexBasis = newState.height;
199
+ }
200
+ // Check for changes
201
+ const widthChanged = states.width !== newState.width;
202
+ const heightChanged = states.height !== newState.height;
203
+ const flexBaseChanged = states.flexBasis !== newState.flexBasis;
204
+ const hasChanges = widthChanged || heightChanged || flexBaseChanged;
205
+ if (hasChanges) {
206
+ this.setState(newState);
207
+ // Call onChange callback if defined
208
+ if (props.onChange) {
209
+ let newSize = {
210
+ width: newState.width,
211
+ height: newState.height
212
+ };
213
+ props.onChange(newSize, event, direction);
214
+ }
215
+ const size = props.size;
216
+ if (size) {
217
+ this.setState({
218
+ width: (_a = size.width) !== null && _a !== void 0 ? _a : 'auto',
219
+ height: (_b = size.height) !== null && _b !== void 0 ? _b : 'auto'
220
+ });
221
+ }
222
+ }
223
+ };
224
+ this.onMouseUp = event => {
225
+ var _a, _b;
226
+ const {
227
+ isResizing,
228
+ direction,
229
+ original
230
+ } = this.getStates();
231
+ if (!isResizing || !this.resizable) {
232
+ return;
233
+ }
234
+ const {
235
+ width: currentWidth,
236
+ height: currentHeight
237
+ } = this.size;
238
+ const delta = {
239
+ width: currentWidth - original.width,
240
+ height: currentHeight - original.height
241
+ };
242
+ const {
243
+ onResizeEnd,
244
+ size
245
+ } = this.getProps();
246
+ // Call onResizeEnd callback if defined
247
+ if (onResizeEnd) {
248
+ onResizeEnd(this.size, event, direction);
249
+ }
250
+ // Update state with new size if provided
251
+ if (size) {
252
+ this.setState({
253
+ width: (_a = size.width) !== null && _a !== void 0 ? _a : 'auto',
254
+ height: (_b = size.height) !== null && _b !== void 0 ? _b : 'auto'
255
+ });
256
+ }
257
+ // Unregister events and update state
258
+ this.unregisterEvents();
259
+ this.setState({
260
+ isResizing: false,
261
+ backgroundStyle: Object.assign(Object.assign({}, this.getStates().backgroundStyle), {
262
+ cursor: 'auto'
263
+ })
264
+ });
265
+ };
266
+ }
267
+ init() {
268
+ if (!this.resizable || !this.window) {
269
+ return;
270
+ }
271
+ const flexBasis = this.window.getComputedStyle(this.resizable).flexBasis;
272
+ this.setState({
273
+ width: this.propSize.width,
274
+ height: this.propSize.height,
275
+ flexBasis: flexBasis !== 'auto' ? flexBasis : undefined
276
+ });
277
+ this.onResizeStart = this.onResizeStart.bind(this);
278
+ this.onMouseMove = this.onMouseMove.bind(this);
279
+ this.onMouseUp = this.onMouseUp.bind(this);
280
+ }
281
+ get parent() {
282
+ if (!this.resizable) {
283
+ return null;
284
+ }
285
+ return this.resizable.parentNode;
286
+ }
287
+ get window() {
288
+ if (!this.resizable) {
289
+ return null;
290
+ }
291
+ if (!this.resizable.ownerDocument) {
292
+ return null;
293
+ }
294
+ return this.resizable.ownerDocument.defaultView;
295
+ }
296
+ get propSize() {
297
+ const porps = this.getProps();
298
+ return porps.size || porps.defaultSize || DEFAULT_SIZE;
299
+ }
300
+ get size() {
301
+ let width = 0;
302
+ let height = 0;
303
+ if (this.resizable && this.window) {
304
+ width = this.resizable.offsetWidth;
305
+ height = this.resizable.offsetHeight;
306
+ }
307
+ return {
308
+ width,
309
+ height
310
+ };
311
+ }
312
+ get sizeStyle() {
313
+ const size = this.getProp('size');
314
+ const getSize = property => {
315
+ var _a;
316
+ const value = this.getStates()[property];
317
+ if (typeof value === 'undefined' || value === 'auto') {
318
+ return 'auto';
319
+ }
320
+ const propSizeValue = (_a = this.propSize) === null || _a === void 0 ? void 0 : _a[property];
321
+ if (propSizeValue === null || propSizeValue === void 0 ? void 0 : propSizeValue.toString().endsWith('%')) {
322
+ if (value.toString().endsWith('%')) {
323
+ return value.toString();
324
+ }
325
+ const parentSize = this.getParentSize();
326
+ const numberValue = Number(value.toString().replace('px', ''));
327
+ const percentValue = numberValue / parentSize[property] * 100;
328
+ return `${percentValue}%`;
329
+ }
330
+ return getStringSize(value);
331
+ };
332
+ const isResizing = this.getStates().isResizing;
333
+ const width = size && typeof size.width !== 'undefined' && !isResizing ? getStringSize(size.width) : getSize('width');
334
+ const height = size && typeof size.height !== 'undefined' && !isResizing ? getStringSize(size.height) : getSize('height');
335
+ return {
336
+ width,
337
+ height
338
+ };
339
+ }
340
+ getParentSize() {
341
+ const appendPseudo = () => {
342
+ if (!this.resizable || !this.window) {
343
+ return null;
344
+ }
345
+ const parent = this.parent;
346
+ if (!parent) {
347
+ return null;
348
+ }
349
+ const pseudoEle = this.window.document.createElement('div');
350
+ pseudoEle.style.width = '100%';
351
+ pseudoEle.style.height = '100%';
352
+ pseudoEle.style.position = 'absolute';
353
+ pseudoEle.style.transform = 'scale(0, 0)';
354
+ pseudoEle.style.left = '0';
355
+ pseudoEle.style.flex = '0 0 100%';
356
+ parent.appendChild(pseudoEle);
357
+ return pseudoEle;
358
+ };
359
+ const removePseudo = pseudo => {
360
+ const parent = this.parent;
361
+ if (!parent) {
362
+ return;
363
+ }
364
+ parent.removeChild(pseudo);
365
+ };
366
+ if (!this.parent) {
367
+ if (!this.window) {
368
+ return {
369
+ width: 0,
370
+ height: 0
371
+ };
372
+ }
373
+ return {
374
+ width: this.window.innerWidth,
375
+ height: this.window.innerHeight
376
+ };
377
+ }
378
+ const pseudoElement = appendPseudo();
379
+ if (!pseudoElement) {
380
+ return {
381
+ width: 0,
382
+ height: 0
383
+ };
384
+ }
385
+ let flexWrapChanged = false;
386
+ const originalFlexWrap = this.parent.style.flexWrap;
387
+ if (originalFlexWrap !== 'wrap') {
388
+ flexWrapChanged = true;
389
+ this.parent.style.flexWrap = 'wrap';
390
+ }
391
+ pseudoElement.style.position = 'relative';
392
+ pseudoElement.style.minWidth = '100%';
393
+ pseudoElement.style.minHeight = '100%';
394
+ const size = {
395
+ width: pseudoElement.offsetWidth,
396
+ height: pseudoElement.offsetHeight
397
+ };
398
+ if (flexWrapChanged) {
399
+ this.parent.style.flexWrap = originalFlexWrap;
400
+ }
401
+ removePseudo(pseudoElement);
402
+ return size;
403
+ }
404
+ registerEvents() {
405
+ this._adapter.registerEvent();
406
+ }
407
+ unregisterEvents() {
408
+ this._adapter.unregisterEvent();
409
+ }
410
+ getCssPropertySize(newSize, property) {
411
+ var _a;
412
+ const propSizeValue = (_a = this.propSize) === null || _a === void 0 ? void 0 : _a[property];
413
+ const state = this.getStates();
414
+ const isAutoSize = state[property] === 'auto' && state.original[property] === newSize && (typeof propSizeValue === 'undefined' || propSizeValue === 'auto');
415
+ return isAutoSize ? 'auto' : newSize;
416
+ }
417
+ calBoundaryMax(maxWidth, maxHeight) {
418
+ const {
419
+ boundsByDirection
420
+ } = this.getProps();
421
+ const {
422
+ direction
423
+ } = this.getStates();
424
+ const isWidthConstrained = boundsByDirection && has('left', direction);
425
+ const isHeightConstrained = boundsByDirection && has('top', direction);
426
+ let maxWidthConstraint;
427
+ let maxHeightConstraint;
428
+ const props = this.getProps();
429
+ if (props.boundElement === 'parent') {
430
+ const parentElement = this.parent;
431
+ if (parentElement) {
432
+ maxWidthConstraint = isWidthConstrained ? this.boundaryRight - this.parentLeft : parentElement.offsetWidth + (this.parentLeft - this.boundaryLeft);
433
+ maxHeightConstraint = isHeightConstrained ? this.boundaryBottom - this.parentTop : parentElement.offsetHeight + (this.parentTop - this.boundaryTop);
434
+ }
435
+ } else if (props.boundElement === 'window' && this.window) {
436
+ maxWidthConstraint = isWidthConstrained ? this.boundaryRight : this.window.innerWidth - this.boundaryLeft;
437
+ maxHeightConstraint = isHeightConstrained ? this.boundaryBottom : this.window.innerHeight - this.boundaryTop;
438
+ } else if (props.boundElement) {
439
+ const boundary = props.boundElement;
440
+ maxWidthConstraint = isWidthConstrained ? this.boundaryRight - this.targetLeft : boundary.offsetWidth + (this.targetLeft - this.boundaryLeft);
441
+ maxHeightConstraint = isHeightConstrained ? this.boundaryBottom - this.targetTop : boundary.offsetHeight + (this.targetTop - this.boundaryTop);
442
+ }
443
+ if (maxWidthConstraint && Number.isFinite(maxWidthConstraint)) {
444
+ maxWidth = maxWidth && maxWidth < maxWidthConstraint ? maxWidth : maxWidthConstraint;
445
+ }
446
+ if (maxHeightConstraint && Number.isFinite(maxHeightConstraint)) {
447
+ maxHeight = maxHeight && maxHeight < maxHeightConstraint ? maxHeight : maxHeightConstraint;
448
+ }
449
+ return {
450
+ maxWidth,
451
+ maxHeight
452
+ };
453
+ }
454
+ calDirectionSize(clientX, clientY) {
455
+ const props = this.getProps();
456
+ const scale = props.scale || 1;
457
+ let aspectRatio = props.ratio;
458
+ const [resizeRatioX, resizeRatioY] = Array.isArray(aspectRatio) ? aspectRatio : [aspectRatio, aspectRatio];
459
+ const {
460
+ direction,
461
+ original
462
+ } = this.getStates();
463
+ const {
464
+ lockAspectRatio,
465
+ lockAspectRatioExtraHeight = 0,
466
+ lockAspectRatioExtraWidth = 0
467
+ } = props;
468
+ let newWidth = original.width;
469
+ let newHeight = original.height;
470
+ const calculateNewWidth = deltaX => original.width + deltaX * resizeRatioX / scale;
471
+ const calculateNewHeight = deltaY => original.height + deltaY * resizeRatioY / scale;
472
+ if (has('top', direction)) {
473
+ newHeight = calculateNewHeight(original.y - clientY);
474
+ if (lockAspectRatio) {
475
+ newWidth = (newHeight - lockAspectRatioExtraHeight) * this.lockAspectRatio + lockAspectRatioExtraWidth;
476
+ }
477
+ }
478
+ if (has('bottom', direction)) {
479
+ newHeight = calculateNewHeight(clientY - original.y);
480
+ if (lockAspectRatio) {
481
+ newWidth = (newHeight - lockAspectRatioExtraHeight) * this.lockAspectRatio + lockAspectRatioExtraWidth;
482
+ }
483
+ }
484
+ if (has('right', direction)) {
485
+ newWidth = calculateNewWidth(clientX - original.x);
486
+ if (lockAspectRatio) {
487
+ newHeight = (newWidth - lockAspectRatioExtraWidth) / this.lockAspectRatio + lockAspectRatioExtraHeight;
488
+ }
489
+ }
490
+ if (has('left', direction)) {
491
+ newWidth = calculateNewWidth(original.x - clientX);
492
+ if (lockAspectRatio) {
493
+ newHeight = (newWidth - lockAspectRatioExtraWidth) / this.lockAspectRatio + lockAspectRatioExtraHeight;
494
+ }
495
+ }
496
+ return {
497
+ newWidth,
498
+ newHeight
499
+ };
500
+ }
501
+ calAspectRatioSize(newWidth, newHeight, max, min) {
502
+ const {
503
+ lockAspectRatio,
504
+ lockAspectRatioExtraHeight = 0,
505
+ lockAspectRatioExtraWidth = 0
506
+ } = this.getProps();
507
+ const minWidth = typeof min.width === 'undefined' ? 10 : min.width;
508
+ const maxWidth = typeof max.width === 'undefined' || max.width < 0 ? newWidth : max.width;
509
+ const minHeight = typeof min.height === 'undefined' ? 10 : min.height;
510
+ const maxHeight = typeof max.height === 'undefined' || max.height < 0 ? newHeight : max.height;
511
+ if (lockAspectRatio) {
512
+ const adjustedMinWidth = (minHeight - lockAspectRatioExtraHeight) * this.lockAspectRatio + lockAspectRatioExtraWidth;
513
+ const adjustedMaxWidth = (maxHeight - lockAspectRatioExtraHeight) * this.lockAspectRatio + lockAspectRatioExtraWidth;
514
+ const adjustedMinHeight = (minWidth - lockAspectRatioExtraWidth) / this.lockAspectRatio + lockAspectRatioExtraHeight;
515
+ const adjustedMaxHeight = (maxWidth - lockAspectRatioExtraWidth) / this.lockAspectRatio + lockAspectRatioExtraHeight;
516
+ const lockedMinWidth = Math.max(minWidth, adjustedMinWidth);
517
+ const lockedMaxWidth = Math.min(maxWidth, adjustedMaxWidth);
518
+ const lockedMinHeight = Math.max(minHeight, adjustedMinHeight);
519
+ const lockedMaxHeight = Math.min(maxHeight, adjustedMaxHeight);
520
+ newWidth = clamp(newWidth, lockedMinWidth, lockedMaxWidth);
521
+ newHeight = clamp(newHeight, lockedMinHeight, lockedMaxHeight);
522
+ } else {
523
+ newWidth = clamp(newWidth, minWidth, maxWidth);
524
+ newHeight = clamp(newHeight, minHeight, maxHeight);
525
+ }
526
+ return {
527
+ newWidth,
528
+ newHeight
529
+ };
530
+ }
531
+ setBoundary() {
532
+ const props = this.getProps();
533
+ // Set parent boundary
534
+ if (props.boundElement === 'parent') {
535
+ const parentElement = this.parent;
536
+ if (parentElement) {
537
+ const parentRect = parentElement.getBoundingClientRect();
538
+ this.parentLeft = parentRect.left;
539
+ this.parentTop = parentRect.top;
540
+ }
541
+ }
542
+ // Set target (HTML element) boundary
543
+ if (props.boundElement && typeof props.boundElement !== 'string') {
544
+ const targetRect = props.boundElement.getBoundingClientRect();
545
+ this.targetLeft = targetRect.left;
546
+ this.targetTop = targetRect.top;
547
+ }
548
+ // Set resizable boundary
549
+ if (this.resizable) {
550
+ const {
551
+ left,
552
+ top,
553
+ right,
554
+ bottom
555
+ } = this.resizable.getBoundingClientRect();
556
+ this.boundaryLeft = left;
557
+ this.boundaryRight = right;
558
+ this.boundaryTop = top;
559
+ this.boundaryBottom = bottom;
560
+ }
561
+ }
562
+ destroy() {
563
+ this.unregisterEvents();
564
+ }
565
+ }