react-resizable-panels 2.0.4 → 2.0.5
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/CHANGELOG.md +4 -0
- package/dist/declarations/src/index.d.ts +3 -1
- package/dist/declarations/src/utils/rects/getIntersectingRectangle.d.ts +2 -0
- package/dist/declarations/src/utils/rects/intersects.d.ts +2 -0
- package/dist/declarations/src/utils/rects/types.d.ts +6 -0
- package/dist/react-resizable-panels.browser.cjs.js +84 -5
- package/dist/react-resizable-panels.browser.cjs.mjs +3 -1
- package/dist/react-resizable-panels.browser.development.cjs.js +84 -5
- package/dist/react-resizable-panels.browser.development.cjs.mjs +3 -1
- package/dist/react-resizable-panels.browser.development.esm.js +83 -6
- package/dist/react-resizable-panels.browser.esm.js +83 -6
- package/dist/react-resizable-panels.cjs.js +84 -5
- package/dist/react-resizable-panels.cjs.mjs +3 -1
- package/dist/react-resizable-panels.development.cjs.js +84 -5
- package/dist/react-resizable-panels.development.cjs.mjs +3 -1
- package/dist/react-resizable-panels.development.esm.js +83 -6
- package/dist/react-resizable-panels.development.node.cjs.js +84 -5
- package/dist/react-resizable-panels.development.node.cjs.mjs +3 -1
- package/dist/react-resizable-panels.development.node.esm.js +83 -6
- package/dist/react-resizable-panels.esm.js +83 -6
- package/dist/react-resizable-panels.node.cjs.js +84 -5
- package/dist/react-resizable-panels.node.cjs.mjs +3 -1
- package/dist/react-resizable-panels.node.esm.js +83 -6
- package/package.json +4 -1
- package/src/PanelResizeHandleRegistry.ts +75 -8
- package/src/index.ts +4 -0
- package/src/utils/rects/getIntersectingRectangle.test.ts +198 -0
- package/src/utils/rects/getIntersectingRectangle.ts +28 -0
- package/src/utils/rects/intersects.test.ts +197 -0
- package/src/utils/rects/intersects.ts +23 -0
- package/src/utils/rects/types.ts +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.0.5
|
|
4
|
+
|
|
5
|
+
- Resize handle hit detection considers [stacking context](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_positioned_layout/Understanding_z-index/Stacking_context) when determining hit detection (#291)
|
|
6
|
+
|
|
3
7
|
## 2.0.4
|
|
4
8
|
|
|
5
9
|
- Fixed `PanelResizeHandle` `onDragging` prop to only be called for the handle being dragged (#289)
|
|
@@ -9,7 +9,9 @@ import { getResizeHandleElement } from "./utils/dom/getResizeHandleElement.js";
|
|
|
9
9
|
import { getResizeHandleElementIndex } from "./utils/dom/getResizeHandleElementIndex.js";
|
|
10
10
|
import { getResizeHandleElementsForGroup } from "./utils/dom/getResizeHandleElementsForGroup.js";
|
|
11
11
|
import { getResizeHandlePanelIds } from "./utils/dom/getResizeHandlePanelIds.js";
|
|
12
|
+
import { getIntersectingRectangle } from "./utils/rects/getIntersectingRectangle.js";
|
|
13
|
+
import { intersects } from "./utils/rects/intersects.js";
|
|
12
14
|
import type { ImperativePanelHandle, PanelOnCollapse, PanelOnExpand, PanelOnResize, PanelProps } from "./Panel.js";
|
|
13
15
|
import type { ImperativePanelGroupHandle, PanelGroupOnLayout, PanelGroupProps, PanelGroupStorage } from "./PanelGroup.js";
|
|
14
16
|
import type { PanelResizeHandleOnDragging, PanelResizeHandleProps } from "./PanelResizeHandle.js";
|
|
15
|
-
export { ImperativePanelGroupHandle, ImperativePanelHandle, PanelGroupOnLayout, PanelGroupProps, PanelGroupStorage, PanelOnCollapse, PanelOnExpand, PanelOnResize, PanelProps, PanelResizeHandleOnDragging, PanelResizeHandleProps, Panel, PanelGroup, PanelResizeHandle, assert, getPanelElement, getPanelElementsForGroup, getPanelGroupElement, getResizeHandleElement, getResizeHandleElementIndex, getResizeHandleElementsForGroup, getResizeHandlePanelIds, };
|
|
17
|
+
export { ImperativePanelGroupHandle, ImperativePanelHandle, PanelGroupOnLayout, PanelGroupProps, PanelGroupStorage, PanelOnCollapse, PanelOnExpand, PanelOnResize, PanelProps, PanelResizeHandleOnDragging, PanelResizeHandleProps, Panel, PanelGroup, PanelResizeHandle, assert, getIntersectingRectangle, intersects, getPanelElement, getPanelElementsForGroup, getPanelGroupElement, getResizeHandleElement, getResizeHandleElementIndex, getResizeHandleElementsForGroup, getResizeHandlePanelIds, };
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var React = require('react');
|
|
6
|
+
var stackingOrder = require('stacking-order');
|
|
6
7
|
|
|
7
8
|
function _interopNamespace(e) {
|
|
8
9
|
if (e && e.__esModule) return e;
|
|
@@ -294,6 +295,14 @@ function getInputType() {
|
|
|
294
295
|
}
|
|
295
296
|
}
|
|
296
297
|
|
|
298
|
+
function intersects(rectOne, rectTwo, strict) {
|
|
299
|
+
if (strict) {
|
|
300
|
+
return rectOne.x < rectTwo.x + rectTwo.width && rectOne.x + rectOne.width > rectTwo.x && rectOne.y < rectTwo.y + rectTwo.height && rectOne.y + rectOne.height > rectTwo.y;
|
|
301
|
+
} else {
|
|
302
|
+
return rectOne.x <= rectTwo.x + rectTwo.width && rectOne.x + rectOne.width >= rectTwo.x && rectOne.y <= rectTwo.y + rectTwo.height && rectOne.y + rectOne.height >= rectTwo.y;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
297
306
|
const EXCEEDED_HORIZONTAL_MIN = 0b0001;
|
|
298
307
|
const EXCEEDED_HORIZONTAL_MAX = 0b0010;
|
|
299
308
|
const EXCEEDED_VERTICAL_MIN = 0b0100;
|
|
@@ -332,12 +341,16 @@ function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins
|
|
|
332
341
|
};
|
|
333
342
|
}
|
|
334
343
|
function handlePointerDown(event) {
|
|
344
|
+
const {
|
|
345
|
+
target
|
|
346
|
+
} = event;
|
|
335
347
|
const {
|
|
336
348
|
x,
|
|
337
349
|
y
|
|
338
350
|
} = getResizeEventCoordinates(event);
|
|
339
351
|
isPointerDown = true;
|
|
340
352
|
recalculateIntersectingHandles({
|
|
353
|
+
target,
|
|
341
354
|
x,
|
|
342
355
|
y
|
|
343
356
|
});
|
|
@@ -353,10 +366,15 @@ function handlePointerMove(event) {
|
|
|
353
366
|
y
|
|
354
367
|
} = getResizeEventCoordinates(event);
|
|
355
368
|
if (!isPointerDown) {
|
|
369
|
+
const {
|
|
370
|
+
target
|
|
371
|
+
} = event;
|
|
372
|
+
|
|
356
373
|
// Recalculate intersecting handles whenever the pointer moves, except if it has already been pressed
|
|
357
374
|
// at that point, the handles may not move with the pointer (depending on constraints)
|
|
358
375
|
// but the same set of active handles should be locked until the pointer is released
|
|
359
376
|
recalculateIntersectingHandles({
|
|
377
|
+
target,
|
|
360
378
|
x,
|
|
361
379
|
y
|
|
362
380
|
});
|
|
@@ -370,6 +388,9 @@ function handlePointerMove(event) {
|
|
|
370
388
|
}
|
|
371
389
|
}
|
|
372
390
|
function handlePointerUp(event) {
|
|
391
|
+
const {
|
|
392
|
+
target
|
|
393
|
+
} = event;
|
|
373
394
|
const {
|
|
374
395
|
x,
|
|
375
396
|
y
|
|
@@ -379,33 +400,72 @@ function handlePointerUp(event) {
|
|
|
379
400
|
if (intersectingHandles.length > 0) {
|
|
380
401
|
event.preventDefault();
|
|
381
402
|
}
|
|
403
|
+
updateResizeHandlerStates("up", event);
|
|
382
404
|
recalculateIntersectingHandles({
|
|
405
|
+
target,
|
|
383
406
|
x,
|
|
384
407
|
y
|
|
385
408
|
});
|
|
386
|
-
updateResizeHandlerStates("up", event);
|
|
387
409
|
updateCursor();
|
|
388
410
|
updateListeners();
|
|
389
411
|
}
|
|
390
412
|
function recalculateIntersectingHandles({
|
|
413
|
+
target,
|
|
391
414
|
x,
|
|
392
415
|
y
|
|
393
416
|
}) {
|
|
394
417
|
intersectingHandles.splice(0);
|
|
418
|
+
let targetElement = null;
|
|
419
|
+
if (target instanceof HTMLElement) {
|
|
420
|
+
targetElement = target;
|
|
421
|
+
}
|
|
395
422
|
registeredResizeHandlers.forEach(data => {
|
|
396
423
|
const {
|
|
397
|
-
element,
|
|
424
|
+
element: dragHandleElement,
|
|
398
425
|
hitAreaMargins
|
|
399
426
|
} = data;
|
|
427
|
+
const dragHandleRect = dragHandleElement.getBoundingClientRect();
|
|
400
428
|
const {
|
|
401
429
|
bottom,
|
|
402
430
|
left,
|
|
403
431
|
right,
|
|
404
432
|
top
|
|
405
|
-
} =
|
|
433
|
+
} = dragHandleRect;
|
|
406
434
|
const margin = isCoarsePointer ? hitAreaMargins.coarse : hitAreaMargins.fine;
|
|
407
|
-
const
|
|
408
|
-
if (
|
|
435
|
+
const eventIntersects = x >= left - margin && x <= right + margin && y >= top - margin && y <= bottom + margin;
|
|
436
|
+
if (eventIntersects) {
|
|
437
|
+
// TRICKY
|
|
438
|
+
// We listen for pointers events at the root in order to support hit area margins
|
|
439
|
+
// (determining when the pointer is close enough to an element to be considered a "hit")
|
|
440
|
+
// Clicking on an element "above" a handle (e.g. a modal) should prevent a hit though
|
|
441
|
+
// so at this point we need to compare stacking order of a potentially intersecting drag handle,
|
|
442
|
+
// and the element that was actually clicked/touched
|
|
443
|
+
if (targetElement !== null && dragHandleElement !== targetElement && !dragHandleElement.contains(targetElement) && !targetElement.contains(dragHandleElement) &&
|
|
444
|
+
// Calculating stacking order has a cost, so we should avoid it if possible
|
|
445
|
+
// That is why we only check potentially intersecting handles,
|
|
446
|
+
// and why we skip if the event target is within the handle's DOM
|
|
447
|
+
stackingOrder.compare(targetElement, dragHandleElement) > 0) {
|
|
448
|
+
// If the target is above the drag handle, then we also need to confirm they overlap
|
|
449
|
+
// If they are beside each other (e.g. a panel and its drag handle) then the handle is still interactive
|
|
450
|
+
//
|
|
451
|
+
// It's not enough to compare only the target
|
|
452
|
+
// The target might be a small element inside of a larger container
|
|
453
|
+
// (For example, a SPAN or a DIV inside of a larger modal dialog)
|
|
454
|
+
let currentElement = targetElement;
|
|
455
|
+
let didIntersect = false;
|
|
456
|
+
while (currentElement) {
|
|
457
|
+
if (currentElement.contains(dragHandleElement)) {
|
|
458
|
+
break;
|
|
459
|
+
} else if (intersects(currentElement.getBoundingClientRect(), dragHandleRect, true)) {
|
|
460
|
+
didIntersect = true;
|
|
461
|
+
break;
|
|
462
|
+
}
|
|
463
|
+
currentElement = currentElement.parentElement;
|
|
464
|
+
}
|
|
465
|
+
if (didIntersect) {
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
409
469
|
intersectingHandles.push(data);
|
|
410
470
|
}
|
|
411
471
|
});
|
|
@@ -2153,10 +2213,28 @@ function getPanelElementsForGroup(groupId, scope = document) {
|
|
|
2153
2213
|
return Array.from(scope.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
2154
2214
|
}
|
|
2155
2215
|
|
|
2216
|
+
function getIntersectingRectangle(rectOne, rectTwo, strict) {
|
|
2217
|
+
if (!intersects(rectOne, rectTwo, strict)) {
|
|
2218
|
+
return {
|
|
2219
|
+
x: 0,
|
|
2220
|
+
y: 0,
|
|
2221
|
+
width: 0,
|
|
2222
|
+
height: 0
|
|
2223
|
+
};
|
|
2224
|
+
}
|
|
2225
|
+
return {
|
|
2226
|
+
x: Math.max(rectOne.x, rectTwo.x),
|
|
2227
|
+
y: Math.max(rectOne.y, rectTwo.y),
|
|
2228
|
+
width: Math.min(rectOne.x + rectOne.width, rectTwo.x + rectTwo.width) - Math.max(rectOne.x, rectTwo.x),
|
|
2229
|
+
height: Math.min(rectOne.y + rectOne.height, rectTwo.y + rectTwo.height) - Math.max(rectOne.y, rectTwo.y)
|
|
2230
|
+
};
|
|
2231
|
+
}
|
|
2232
|
+
|
|
2156
2233
|
exports.Panel = Panel;
|
|
2157
2234
|
exports.PanelGroup = PanelGroup;
|
|
2158
2235
|
exports.PanelResizeHandle = PanelResizeHandle;
|
|
2159
2236
|
exports.assert = assert;
|
|
2237
|
+
exports.getIntersectingRectangle = getIntersectingRectangle;
|
|
2160
2238
|
exports.getPanelElement = getPanelElement;
|
|
2161
2239
|
exports.getPanelElementsForGroup = getPanelElementsForGroup;
|
|
2162
2240
|
exports.getPanelGroupElement = getPanelGroupElement;
|
|
@@ -2164,3 +2242,4 @@ exports.getResizeHandleElement = getResizeHandleElement;
|
|
|
2164
2242
|
exports.getResizeHandleElementIndex = getResizeHandleElementIndex;
|
|
2165
2243
|
exports.getResizeHandleElementsForGroup = getResizeHandleElementsForGroup;
|
|
2166
2244
|
exports.getResizeHandlePanelIds = getResizeHandlePanelIds;
|
|
2245
|
+
exports.intersects = intersects;
|
|
@@ -3,11 +3,13 @@ export {
|
|
|
3
3
|
PanelGroup,
|
|
4
4
|
PanelResizeHandle,
|
|
5
5
|
assert,
|
|
6
|
+
getIntersectingRectangle,
|
|
6
7
|
getPanelElement,
|
|
7
8
|
getPanelElementsForGroup,
|
|
8
9
|
getPanelGroupElement,
|
|
9
10
|
getResizeHandleElement,
|
|
10
11
|
getResizeHandleElementIndex,
|
|
11
12
|
getResizeHandleElementsForGroup,
|
|
12
|
-
getResizeHandlePanelIds
|
|
13
|
+
getResizeHandlePanelIds,
|
|
14
|
+
intersects
|
|
13
15
|
} from "./react-resizable-panels.browser.cjs.js";
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var React = require('react');
|
|
6
|
+
var stackingOrder = require('stacking-order');
|
|
6
7
|
|
|
7
8
|
function _interopNamespace(e) {
|
|
8
9
|
if (e && e.__esModule) return e;
|
|
@@ -300,6 +301,14 @@ function getInputType() {
|
|
|
300
301
|
}
|
|
301
302
|
}
|
|
302
303
|
|
|
304
|
+
function intersects(rectOne, rectTwo, strict) {
|
|
305
|
+
if (strict) {
|
|
306
|
+
return rectOne.x < rectTwo.x + rectTwo.width && rectOne.x + rectOne.width > rectTwo.x && rectOne.y < rectTwo.y + rectTwo.height && rectOne.y + rectOne.height > rectTwo.y;
|
|
307
|
+
} else {
|
|
308
|
+
return rectOne.x <= rectTwo.x + rectTwo.width && rectOne.x + rectOne.width >= rectTwo.x && rectOne.y <= rectTwo.y + rectTwo.height && rectOne.y + rectOne.height >= rectTwo.y;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
303
312
|
const EXCEEDED_HORIZONTAL_MIN = 0b0001;
|
|
304
313
|
const EXCEEDED_HORIZONTAL_MAX = 0b0010;
|
|
305
314
|
const EXCEEDED_VERTICAL_MIN = 0b0100;
|
|
@@ -338,12 +347,16 @@ function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins
|
|
|
338
347
|
};
|
|
339
348
|
}
|
|
340
349
|
function handlePointerDown(event) {
|
|
350
|
+
const {
|
|
351
|
+
target
|
|
352
|
+
} = event;
|
|
341
353
|
const {
|
|
342
354
|
x,
|
|
343
355
|
y
|
|
344
356
|
} = getResizeEventCoordinates(event);
|
|
345
357
|
isPointerDown = true;
|
|
346
358
|
recalculateIntersectingHandles({
|
|
359
|
+
target,
|
|
347
360
|
x,
|
|
348
361
|
y
|
|
349
362
|
});
|
|
@@ -359,10 +372,15 @@ function handlePointerMove(event) {
|
|
|
359
372
|
y
|
|
360
373
|
} = getResizeEventCoordinates(event);
|
|
361
374
|
if (!isPointerDown) {
|
|
375
|
+
const {
|
|
376
|
+
target
|
|
377
|
+
} = event;
|
|
378
|
+
|
|
362
379
|
// Recalculate intersecting handles whenever the pointer moves, except if it has already been pressed
|
|
363
380
|
// at that point, the handles may not move with the pointer (depending on constraints)
|
|
364
381
|
// but the same set of active handles should be locked until the pointer is released
|
|
365
382
|
recalculateIntersectingHandles({
|
|
383
|
+
target,
|
|
366
384
|
x,
|
|
367
385
|
y
|
|
368
386
|
});
|
|
@@ -376,6 +394,9 @@ function handlePointerMove(event) {
|
|
|
376
394
|
}
|
|
377
395
|
}
|
|
378
396
|
function handlePointerUp(event) {
|
|
397
|
+
const {
|
|
398
|
+
target
|
|
399
|
+
} = event;
|
|
379
400
|
const {
|
|
380
401
|
x,
|
|
381
402
|
y
|
|
@@ -385,33 +406,72 @@ function handlePointerUp(event) {
|
|
|
385
406
|
if (intersectingHandles.length > 0) {
|
|
386
407
|
event.preventDefault();
|
|
387
408
|
}
|
|
409
|
+
updateResizeHandlerStates("up", event);
|
|
388
410
|
recalculateIntersectingHandles({
|
|
411
|
+
target,
|
|
389
412
|
x,
|
|
390
413
|
y
|
|
391
414
|
});
|
|
392
|
-
updateResizeHandlerStates("up", event);
|
|
393
415
|
updateCursor();
|
|
394
416
|
updateListeners();
|
|
395
417
|
}
|
|
396
418
|
function recalculateIntersectingHandles({
|
|
419
|
+
target,
|
|
397
420
|
x,
|
|
398
421
|
y
|
|
399
422
|
}) {
|
|
400
423
|
intersectingHandles.splice(0);
|
|
424
|
+
let targetElement = null;
|
|
425
|
+
if (target instanceof HTMLElement) {
|
|
426
|
+
targetElement = target;
|
|
427
|
+
}
|
|
401
428
|
registeredResizeHandlers.forEach(data => {
|
|
402
429
|
const {
|
|
403
|
-
element,
|
|
430
|
+
element: dragHandleElement,
|
|
404
431
|
hitAreaMargins
|
|
405
432
|
} = data;
|
|
433
|
+
const dragHandleRect = dragHandleElement.getBoundingClientRect();
|
|
406
434
|
const {
|
|
407
435
|
bottom,
|
|
408
436
|
left,
|
|
409
437
|
right,
|
|
410
438
|
top
|
|
411
|
-
} =
|
|
439
|
+
} = dragHandleRect;
|
|
412
440
|
const margin = isCoarsePointer ? hitAreaMargins.coarse : hitAreaMargins.fine;
|
|
413
|
-
const
|
|
414
|
-
if (
|
|
441
|
+
const eventIntersects = x >= left - margin && x <= right + margin && y >= top - margin && y <= bottom + margin;
|
|
442
|
+
if (eventIntersects) {
|
|
443
|
+
// TRICKY
|
|
444
|
+
// We listen for pointers events at the root in order to support hit area margins
|
|
445
|
+
// (determining when the pointer is close enough to an element to be considered a "hit")
|
|
446
|
+
// Clicking on an element "above" a handle (e.g. a modal) should prevent a hit though
|
|
447
|
+
// so at this point we need to compare stacking order of a potentially intersecting drag handle,
|
|
448
|
+
// and the element that was actually clicked/touched
|
|
449
|
+
if (targetElement !== null && dragHandleElement !== targetElement && !dragHandleElement.contains(targetElement) && !targetElement.contains(dragHandleElement) &&
|
|
450
|
+
// Calculating stacking order has a cost, so we should avoid it if possible
|
|
451
|
+
// That is why we only check potentially intersecting handles,
|
|
452
|
+
// and why we skip if the event target is within the handle's DOM
|
|
453
|
+
stackingOrder.compare(targetElement, dragHandleElement) > 0) {
|
|
454
|
+
// If the target is above the drag handle, then we also need to confirm they overlap
|
|
455
|
+
// If they are beside each other (e.g. a panel and its drag handle) then the handle is still interactive
|
|
456
|
+
//
|
|
457
|
+
// It's not enough to compare only the target
|
|
458
|
+
// The target might be a small element inside of a larger container
|
|
459
|
+
// (For example, a SPAN or a DIV inside of a larger modal dialog)
|
|
460
|
+
let currentElement = targetElement;
|
|
461
|
+
let didIntersect = false;
|
|
462
|
+
while (currentElement) {
|
|
463
|
+
if (currentElement.contains(dragHandleElement)) {
|
|
464
|
+
break;
|
|
465
|
+
} else if (intersects(currentElement.getBoundingClientRect(), dragHandleRect, true)) {
|
|
466
|
+
didIntersect = true;
|
|
467
|
+
break;
|
|
468
|
+
}
|
|
469
|
+
currentElement = currentElement.parentElement;
|
|
470
|
+
}
|
|
471
|
+
if (didIntersect) {
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
415
475
|
intersectingHandles.push(data);
|
|
416
476
|
}
|
|
417
477
|
});
|
|
@@ -2259,10 +2319,28 @@ function getPanelElementsForGroup(groupId, scope = document) {
|
|
|
2259
2319
|
return Array.from(scope.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
2260
2320
|
}
|
|
2261
2321
|
|
|
2322
|
+
function getIntersectingRectangle(rectOne, rectTwo, strict) {
|
|
2323
|
+
if (!intersects(rectOne, rectTwo, strict)) {
|
|
2324
|
+
return {
|
|
2325
|
+
x: 0,
|
|
2326
|
+
y: 0,
|
|
2327
|
+
width: 0,
|
|
2328
|
+
height: 0
|
|
2329
|
+
};
|
|
2330
|
+
}
|
|
2331
|
+
return {
|
|
2332
|
+
x: Math.max(rectOne.x, rectTwo.x),
|
|
2333
|
+
y: Math.max(rectOne.y, rectTwo.y),
|
|
2334
|
+
width: Math.min(rectOne.x + rectOne.width, rectTwo.x + rectTwo.width) - Math.max(rectOne.x, rectTwo.x),
|
|
2335
|
+
height: Math.min(rectOne.y + rectOne.height, rectTwo.y + rectTwo.height) - Math.max(rectOne.y, rectTwo.y)
|
|
2336
|
+
};
|
|
2337
|
+
}
|
|
2338
|
+
|
|
2262
2339
|
exports.Panel = Panel;
|
|
2263
2340
|
exports.PanelGroup = PanelGroup;
|
|
2264
2341
|
exports.PanelResizeHandle = PanelResizeHandle;
|
|
2265
2342
|
exports.assert = assert;
|
|
2343
|
+
exports.getIntersectingRectangle = getIntersectingRectangle;
|
|
2266
2344
|
exports.getPanelElement = getPanelElement;
|
|
2267
2345
|
exports.getPanelElementsForGroup = getPanelElementsForGroup;
|
|
2268
2346
|
exports.getPanelGroupElement = getPanelGroupElement;
|
|
@@ -2270,3 +2348,4 @@ exports.getResizeHandleElement = getResizeHandleElement;
|
|
|
2270
2348
|
exports.getResizeHandleElementIndex = getResizeHandleElementIndex;
|
|
2271
2349
|
exports.getResizeHandleElementsForGroup = getResizeHandleElementsForGroup;
|
|
2272
2350
|
exports.getResizeHandlePanelIds = getResizeHandlePanelIds;
|
|
2351
|
+
exports.intersects = intersects;
|
|
@@ -3,11 +3,13 @@ export {
|
|
|
3
3
|
PanelGroup,
|
|
4
4
|
PanelResizeHandle,
|
|
5
5
|
assert,
|
|
6
|
+
getIntersectingRectangle,
|
|
6
7
|
getPanelElement,
|
|
7
8
|
getPanelElementsForGroup,
|
|
8
9
|
getPanelGroupElement,
|
|
9
10
|
getResizeHandleElement,
|
|
10
11
|
getResizeHandleElementIndex,
|
|
11
12
|
getResizeHandleElementsForGroup,
|
|
12
|
-
getResizeHandlePanelIds
|
|
13
|
+
getResizeHandlePanelIds,
|
|
14
|
+
intersects
|
|
13
15
|
} from "./react-resizable-panels.browser.development.cjs.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { compare } from 'stacking-order';
|
|
2
3
|
|
|
3
4
|
// This module exists to work around Webpack issue https://github.com/webpack/webpack/issues/14814
|
|
4
5
|
|
|
@@ -276,6 +277,14 @@ function getInputType() {
|
|
|
276
277
|
}
|
|
277
278
|
}
|
|
278
279
|
|
|
280
|
+
function intersects(rectOne, rectTwo, strict) {
|
|
281
|
+
if (strict) {
|
|
282
|
+
return rectOne.x < rectTwo.x + rectTwo.width && rectOne.x + rectOne.width > rectTwo.x && rectOne.y < rectTwo.y + rectTwo.height && rectOne.y + rectOne.height > rectTwo.y;
|
|
283
|
+
} else {
|
|
284
|
+
return rectOne.x <= rectTwo.x + rectTwo.width && rectOne.x + rectOne.width >= rectTwo.x && rectOne.y <= rectTwo.y + rectTwo.height && rectOne.y + rectOne.height >= rectTwo.y;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
279
288
|
const EXCEEDED_HORIZONTAL_MIN = 0b0001;
|
|
280
289
|
const EXCEEDED_HORIZONTAL_MAX = 0b0010;
|
|
281
290
|
const EXCEEDED_VERTICAL_MIN = 0b0100;
|
|
@@ -314,12 +323,16 @@ function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins
|
|
|
314
323
|
};
|
|
315
324
|
}
|
|
316
325
|
function handlePointerDown(event) {
|
|
326
|
+
const {
|
|
327
|
+
target
|
|
328
|
+
} = event;
|
|
317
329
|
const {
|
|
318
330
|
x,
|
|
319
331
|
y
|
|
320
332
|
} = getResizeEventCoordinates(event);
|
|
321
333
|
isPointerDown = true;
|
|
322
334
|
recalculateIntersectingHandles({
|
|
335
|
+
target,
|
|
323
336
|
x,
|
|
324
337
|
y
|
|
325
338
|
});
|
|
@@ -335,10 +348,15 @@ function handlePointerMove(event) {
|
|
|
335
348
|
y
|
|
336
349
|
} = getResizeEventCoordinates(event);
|
|
337
350
|
if (!isPointerDown) {
|
|
351
|
+
const {
|
|
352
|
+
target
|
|
353
|
+
} = event;
|
|
354
|
+
|
|
338
355
|
// Recalculate intersecting handles whenever the pointer moves, except if it has already been pressed
|
|
339
356
|
// at that point, the handles may not move with the pointer (depending on constraints)
|
|
340
357
|
// but the same set of active handles should be locked until the pointer is released
|
|
341
358
|
recalculateIntersectingHandles({
|
|
359
|
+
target,
|
|
342
360
|
x,
|
|
343
361
|
y
|
|
344
362
|
});
|
|
@@ -352,6 +370,9 @@ function handlePointerMove(event) {
|
|
|
352
370
|
}
|
|
353
371
|
}
|
|
354
372
|
function handlePointerUp(event) {
|
|
373
|
+
const {
|
|
374
|
+
target
|
|
375
|
+
} = event;
|
|
355
376
|
const {
|
|
356
377
|
x,
|
|
357
378
|
y
|
|
@@ -361,33 +382,72 @@ function handlePointerUp(event) {
|
|
|
361
382
|
if (intersectingHandles.length > 0) {
|
|
362
383
|
event.preventDefault();
|
|
363
384
|
}
|
|
385
|
+
updateResizeHandlerStates("up", event);
|
|
364
386
|
recalculateIntersectingHandles({
|
|
387
|
+
target,
|
|
365
388
|
x,
|
|
366
389
|
y
|
|
367
390
|
});
|
|
368
|
-
updateResizeHandlerStates("up", event);
|
|
369
391
|
updateCursor();
|
|
370
392
|
updateListeners();
|
|
371
393
|
}
|
|
372
394
|
function recalculateIntersectingHandles({
|
|
395
|
+
target,
|
|
373
396
|
x,
|
|
374
397
|
y
|
|
375
398
|
}) {
|
|
376
399
|
intersectingHandles.splice(0);
|
|
400
|
+
let targetElement = null;
|
|
401
|
+
if (target instanceof HTMLElement) {
|
|
402
|
+
targetElement = target;
|
|
403
|
+
}
|
|
377
404
|
registeredResizeHandlers.forEach(data => {
|
|
378
405
|
const {
|
|
379
|
-
element,
|
|
406
|
+
element: dragHandleElement,
|
|
380
407
|
hitAreaMargins
|
|
381
408
|
} = data;
|
|
409
|
+
const dragHandleRect = dragHandleElement.getBoundingClientRect();
|
|
382
410
|
const {
|
|
383
411
|
bottom,
|
|
384
412
|
left,
|
|
385
413
|
right,
|
|
386
414
|
top
|
|
387
|
-
} =
|
|
415
|
+
} = dragHandleRect;
|
|
388
416
|
const margin = isCoarsePointer ? hitAreaMargins.coarse : hitAreaMargins.fine;
|
|
389
|
-
const
|
|
390
|
-
if (
|
|
417
|
+
const eventIntersects = x >= left - margin && x <= right + margin && y >= top - margin && y <= bottom + margin;
|
|
418
|
+
if (eventIntersects) {
|
|
419
|
+
// TRICKY
|
|
420
|
+
// We listen for pointers events at the root in order to support hit area margins
|
|
421
|
+
// (determining when the pointer is close enough to an element to be considered a "hit")
|
|
422
|
+
// Clicking on an element "above" a handle (e.g. a modal) should prevent a hit though
|
|
423
|
+
// so at this point we need to compare stacking order of a potentially intersecting drag handle,
|
|
424
|
+
// and the element that was actually clicked/touched
|
|
425
|
+
if (targetElement !== null && dragHandleElement !== targetElement && !dragHandleElement.contains(targetElement) && !targetElement.contains(dragHandleElement) &&
|
|
426
|
+
// Calculating stacking order has a cost, so we should avoid it if possible
|
|
427
|
+
// That is why we only check potentially intersecting handles,
|
|
428
|
+
// and why we skip if the event target is within the handle's DOM
|
|
429
|
+
compare(targetElement, dragHandleElement) > 0) {
|
|
430
|
+
// If the target is above the drag handle, then we also need to confirm they overlap
|
|
431
|
+
// If they are beside each other (e.g. a panel and its drag handle) then the handle is still interactive
|
|
432
|
+
//
|
|
433
|
+
// It's not enough to compare only the target
|
|
434
|
+
// The target might be a small element inside of a larger container
|
|
435
|
+
// (For example, a SPAN or a DIV inside of a larger modal dialog)
|
|
436
|
+
let currentElement = targetElement;
|
|
437
|
+
let didIntersect = false;
|
|
438
|
+
while (currentElement) {
|
|
439
|
+
if (currentElement.contains(dragHandleElement)) {
|
|
440
|
+
break;
|
|
441
|
+
} else if (intersects(currentElement.getBoundingClientRect(), dragHandleRect, true)) {
|
|
442
|
+
didIntersect = true;
|
|
443
|
+
break;
|
|
444
|
+
}
|
|
445
|
+
currentElement = currentElement.parentElement;
|
|
446
|
+
}
|
|
447
|
+
if (didIntersect) {
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
391
451
|
intersectingHandles.push(data);
|
|
392
452
|
}
|
|
393
453
|
});
|
|
@@ -2235,4 +2295,21 @@ function getPanelElementsForGroup(groupId, scope = document) {
|
|
|
2235
2295
|
return Array.from(scope.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
2236
2296
|
}
|
|
2237
2297
|
|
|
2238
|
-
|
|
2298
|
+
function getIntersectingRectangle(rectOne, rectTwo, strict) {
|
|
2299
|
+
if (!intersects(rectOne, rectTwo, strict)) {
|
|
2300
|
+
return {
|
|
2301
|
+
x: 0,
|
|
2302
|
+
y: 0,
|
|
2303
|
+
width: 0,
|
|
2304
|
+
height: 0
|
|
2305
|
+
};
|
|
2306
|
+
}
|
|
2307
|
+
return {
|
|
2308
|
+
x: Math.max(rectOne.x, rectTwo.x),
|
|
2309
|
+
y: Math.max(rectOne.y, rectTwo.y),
|
|
2310
|
+
width: Math.min(rectOne.x + rectOne.width, rectTwo.x + rectTwo.width) - Math.max(rectOne.x, rectTwo.x),
|
|
2311
|
+
height: Math.min(rectOne.y + rectOne.height, rectTwo.y + rectTwo.height) - Math.max(rectOne.y, rectTwo.y)
|
|
2312
|
+
};
|
|
2313
|
+
}
|
|
2314
|
+
|
|
2315
|
+
export { Panel, PanelGroup, PanelResizeHandle, assert, getIntersectingRectangle, getPanelElement, getPanelElementsForGroup, getPanelGroupElement, getResizeHandleElement, getResizeHandleElementIndex, getResizeHandleElementsForGroup, getResizeHandlePanelIds, intersects };
|