react-resizable-panels 2.0.3 → 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 +8 -0
- package/dist/declarations/src/PanelResizeHandle.d.ts +1 -0
- package/dist/declarations/src/PanelResizeHandleRegistry.d.ts +1 -2
- 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 +138 -56
- package/dist/react-resizable-panels.browser.cjs.mjs +3 -1
- package/dist/react-resizable-panels.browser.development.cjs.js +138 -56
- package/dist/react-resizable-panels.browser.development.cjs.mjs +3 -1
- package/dist/react-resizable-panels.browser.development.esm.js +137 -57
- package/dist/react-resizable-panels.browser.esm.js +137 -57
- package/dist/react-resizable-panels.cjs.js +138 -56
- package/dist/react-resizable-panels.cjs.mjs +3 -1
- package/dist/react-resizable-panels.development.cjs.js +138 -56
- package/dist/react-resizable-panels.development.cjs.mjs +3 -1
- package/dist/react-resizable-panels.development.esm.js +137 -57
- package/dist/react-resizable-panels.development.node.cjs.js +138 -56
- package/dist/react-resizable-panels.development.node.cjs.mjs +3 -1
- package/dist/react-resizable-panels.development.node.esm.js +137 -57
- package/dist/react-resizable-panels.esm.js +137 -57
- package/dist/react-resizable-panels.node.cjs.js +138 -56
- package/dist/react-resizable-panels.node.cjs.mjs +3 -1
- package/dist/react-resizable-panels.node.esm.js +137 -57
- package/package.json +4 -1
- package/src/Panel.test.tsx +63 -0
- package/src/PanelGroup.test.tsx +21 -1
- package/src/PanelResizeHandle.test.tsx +181 -22
- package/src/PanelResizeHandle.ts +44 -24
- package/src/PanelResizeHandleRegistry.ts +87 -30
- 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/src/utils/test-utils.ts +39 -0
|
@@ -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;
|
|
@@ -307,6 +308,14 @@ function getInputType() {
|
|
|
307
308
|
}
|
|
308
309
|
}
|
|
309
310
|
|
|
311
|
+
function intersects(rectOne, rectTwo, strict) {
|
|
312
|
+
if (strict) {
|
|
313
|
+
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;
|
|
314
|
+
} else {
|
|
315
|
+
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;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
310
319
|
const EXCEEDED_HORIZONTAL_MIN = 0b0001;
|
|
311
320
|
const EXCEEDED_HORIZONTAL_MAX = 0b0010;
|
|
312
321
|
const EXCEEDED_VERTICAL_MIN = 0b0100;
|
|
@@ -345,12 +354,16 @@ function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins
|
|
|
345
354
|
};
|
|
346
355
|
}
|
|
347
356
|
function handlePointerDown(event) {
|
|
357
|
+
const {
|
|
358
|
+
target
|
|
359
|
+
} = event;
|
|
348
360
|
const {
|
|
349
361
|
x,
|
|
350
362
|
y
|
|
351
363
|
} = getResizeEventCoordinates(event);
|
|
352
364
|
isPointerDown = true;
|
|
353
365
|
recalculateIntersectingHandles({
|
|
366
|
+
target,
|
|
354
367
|
x,
|
|
355
368
|
y
|
|
356
369
|
});
|
|
@@ -365,29 +378,32 @@ function handlePointerMove(event) {
|
|
|
365
378
|
x,
|
|
366
379
|
y
|
|
367
380
|
} = getResizeEventCoordinates(event);
|
|
368
|
-
if (isPointerDown) {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
} = data;
|
|
373
|
-
setResizeHandlerState("move", "drag", event);
|
|
374
|
-
});
|
|
381
|
+
if (!isPointerDown) {
|
|
382
|
+
const {
|
|
383
|
+
target
|
|
384
|
+
} = event;
|
|
375
385
|
|
|
376
|
-
//
|
|
377
|
-
|
|
378
|
-
|
|
386
|
+
// Recalculate intersecting handles whenever the pointer moves, except if it has already been pressed
|
|
387
|
+
// at that point, the handles may not move with the pointer (depending on constraints)
|
|
388
|
+
// but the same set of active handles should be locked until the pointer is released
|
|
379
389
|
recalculateIntersectingHandles({
|
|
390
|
+
target,
|
|
380
391
|
x,
|
|
381
392
|
y
|
|
382
393
|
});
|
|
383
|
-
updateResizeHandlerStates("move", event);
|
|
384
|
-
updateCursor();
|
|
385
394
|
}
|
|
395
|
+
updateResizeHandlerStates("move", event);
|
|
396
|
+
|
|
397
|
+
// Update cursor based on return value(s) from active handles
|
|
398
|
+
updateCursor();
|
|
386
399
|
if (intersectingHandles.length > 0) {
|
|
387
400
|
event.preventDefault();
|
|
388
401
|
}
|
|
389
402
|
}
|
|
390
403
|
function handlePointerUp(event) {
|
|
404
|
+
const {
|
|
405
|
+
target
|
|
406
|
+
} = event;
|
|
391
407
|
const {
|
|
392
408
|
x,
|
|
393
409
|
y
|
|
@@ -397,33 +413,72 @@ function handlePointerUp(event) {
|
|
|
397
413
|
if (intersectingHandles.length > 0) {
|
|
398
414
|
event.preventDefault();
|
|
399
415
|
}
|
|
416
|
+
updateResizeHandlerStates("up", event);
|
|
400
417
|
recalculateIntersectingHandles({
|
|
418
|
+
target,
|
|
401
419
|
x,
|
|
402
420
|
y
|
|
403
421
|
});
|
|
404
|
-
updateResizeHandlerStates("up", event);
|
|
405
422
|
updateCursor();
|
|
406
423
|
updateListeners();
|
|
407
424
|
}
|
|
408
425
|
function recalculateIntersectingHandles({
|
|
426
|
+
target,
|
|
409
427
|
x,
|
|
410
428
|
y
|
|
411
429
|
}) {
|
|
412
430
|
intersectingHandles.splice(0);
|
|
431
|
+
let targetElement = null;
|
|
432
|
+
if (target instanceof HTMLElement) {
|
|
433
|
+
targetElement = target;
|
|
434
|
+
}
|
|
413
435
|
registeredResizeHandlers.forEach(data => {
|
|
414
436
|
const {
|
|
415
|
-
element,
|
|
437
|
+
element: dragHandleElement,
|
|
416
438
|
hitAreaMargins
|
|
417
439
|
} = data;
|
|
440
|
+
const dragHandleRect = dragHandleElement.getBoundingClientRect();
|
|
418
441
|
const {
|
|
419
442
|
bottom,
|
|
420
443
|
left,
|
|
421
444
|
right,
|
|
422
445
|
top
|
|
423
|
-
} =
|
|
446
|
+
} = dragHandleRect;
|
|
424
447
|
const margin = isCoarsePointer ? hitAreaMargins.coarse : hitAreaMargins.fine;
|
|
425
|
-
const
|
|
426
|
-
if (
|
|
448
|
+
const eventIntersects = x >= left - margin && x <= right + margin && y >= top - margin && y <= bottom + margin;
|
|
449
|
+
if (eventIntersects) {
|
|
450
|
+
// TRICKY
|
|
451
|
+
// We listen for pointers events at the root in order to support hit area margins
|
|
452
|
+
// (determining when the pointer is close enough to an element to be considered a "hit")
|
|
453
|
+
// Clicking on an element "above" a handle (e.g. a modal) should prevent a hit though
|
|
454
|
+
// so at this point we need to compare stacking order of a potentially intersecting drag handle,
|
|
455
|
+
// and the element that was actually clicked/touched
|
|
456
|
+
if (targetElement !== null && dragHandleElement !== targetElement && !dragHandleElement.contains(targetElement) && !targetElement.contains(dragHandleElement) &&
|
|
457
|
+
// Calculating stacking order has a cost, so we should avoid it if possible
|
|
458
|
+
// That is why we only check potentially intersecting handles,
|
|
459
|
+
// and why we skip if the event target is within the handle's DOM
|
|
460
|
+
stackingOrder.compare(targetElement, dragHandleElement) > 0) {
|
|
461
|
+
// If the target is above the drag handle, then we also need to confirm they overlap
|
|
462
|
+
// If they are beside each other (e.g. a panel and its drag handle) then the handle is still interactive
|
|
463
|
+
//
|
|
464
|
+
// It's not enough to compare only the target
|
|
465
|
+
// The target might be a small element inside of a larger container
|
|
466
|
+
// (For example, a SPAN or a DIV inside of a larger modal dialog)
|
|
467
|
+
let currentElement = targetElement;
|
|
468
|
+
let didIntersect = false;
|
|
469
|
+
while (currentElement) {
|
|
470
|
+
if (currentElement.contains(dragHandleElement)) {
|
|
471
|
+
break;
|
|
472
|
+
} else if (intersects(currentElement.getBoundingClientRect(), dragHandleRect, true)) {
|
|
473
|
+
didIntersect = true;
|
|
474
|
+
break;
|
|
475
|
+
}
|
|
476
|
+
currentElement = currentElement.parentElement;
|
|
477
|
+
}
|
|
478
|
+
if (didIntersect) {
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
427
482
|
intersectingHandles.push(data);
|
|
428
483
|
}
|
|
429
484
|
});
|
|
@@ -515,15 +570,8 @@ function updateResizeHandlerStates(action, event) {
|
|
|
515
570
|
const {
|
|
516
571
|
setResizeHandlerState
|
|
517
572
|
} = data;
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
setResizeHandlerState(action, "drag", event);
|
|
521
|
-
} else {
|
|
522
|
-
setResizeHandlerState(action, "hover", event);
|
|
523
|
-
}
|
|
524
|
-
} else {
|
|
525
|
-
setResizeHandlerState(action, "inactive", event);
|
|
526
|
-
}
|
|
573
|
+
const isActive = intersectingHandles.includes(data);
|
|
574
|
+
setResizeHandlerState(action, isActive, event);
|
|
527
575
|
});
|
|
528
576
|
}
|
|
529
577
|
|
|
@@ -2160,6 +2208,12 @@ function PanelResizeHandle({
|
|
|
2160
2208
|
const [state, setState] = useState("inactive");
|
|
2161
2209
|
const [isFocused, setIsFocused] = useState(false);
|
|
2162
2210
|
const [resizeHandler, setResizeHandler] = useState(null);
|
|
2211
|
+
const committedValuesRef = useRef({
|
|
2212
|
+
state
|
|
2213
|
+
});
|
|
2214
|
+
useLayoutEffect(() => {
|
|
2215
|
+
committedValuesRef.current.state = state;
|
|
2216
|
+
});
|
|
2163
2217
|
useEffect(() => {
|
|
2164
2218
|
if (disabled) {
|
|
2165
2219
|
setResizeHandler(null);
|
|
@@ -2175,38 +2229,47 @@ function PanelResizeHandle({
|
|
|
2175
2229
|
}
|
|
2176
2230
|
const element = elementRef.current;
|
|
2177
2231
|
assert(element);
|
|
2178
|
-
const setResizeHandlerState = (action,
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
onDragging
|
|
2232
|
+
const setResizeHandlerState = (action, isActive, event) => {
|
|
2233
|
+
if (isActive) {
|
|
2234
|
+
switch (action) {
|
|
2235
|
+
case "down":
|
|
2236
|
+
{
|
|
2237
|
+
setState("drag");
|
|
2238
|
+
startDragging(resizeHandleId, event);
|
|
2239
|
+
const {
|
|
2240
|
+
onDragging
|
|
2241
|
+
} = callbacksRef.current;
|
|
2242
|
+
if (onDragging) {
|
|
2243
|
+
onDragging(true);
|
|
2244
|
+
}
|
|
2245
|
+
break;
|
|
2189
2246
|
}
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2247
|
+
case "move":
|
|
2248
|
+
{
|
|
2249
|
+
const {
|
|
2250
|
+
state
|
|
2251
|
+
} = committedValuesRef.current;
|
|
2252
|
+
if (state !== "drag") {
|
|
2253
|
+
setState("hover");
|
|
2254
|
+
}
|
|
2255
|
+
resizeHandler(event);
|
|
2256
|
+
break;
|
|
2200
2257
|
}
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2258
|
+
case "up":
|
|
2259
|
+
{
|
|
2260
|
+
setState("hover");
|
|
2261
|
+
stopDragging();
|
|
2262
|
+
const {
|
|
2263
|
+
onDragging
|
|
2264
|
+
} = callbacksRef.current;
|
|
2265
|
+
if (onDragging) {
|
|
2266
|
+
onDragging(false);
|
|
2267
|
+
}
|
|
2268
|
+
break;
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2271
|
+
} else {
|
|
2272
|
+
setState("inactive");
|
|
2210
2273
|
}
|
|
2211
2274
|
};
|
|
2212
2275
|
return registerResizeHandle(resizeHandleId, element, direction, {
|
|
@@ -2263,10 +2326,28 @@ function getPanelElementsForGroup(groupId, scope = document) {
|
|
|
2263
2326
|
return Array.from(scope.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
2264
2327
|
}
|
|
2265
2328
|
|
|
2329
|
+
function getIntersectingRectangle(rectOne, rectTwo, strict) {
|
|
2330
|
+
if (!intersects(rectOne, rectTwo, strict)) {
|
|
2331
|
+
return {
|
|
2332
|
+
x: 0,
|
|
2333
|
+
y: 0,
|
|
2334
|
+
width: 0,
|
|
2335
|
+
height: 0
|
|
2336
|
+
};
|
|
2337
|
+
}
|
|
2338
|
+
return {
|
|
2339
|
+
x: Math.max(rectOne.x, rectTwo.x),
|
|
2340
|
+
y: Math.max(rectOne.y, rectTwo.y),
|
|
2341
|
+
width: Math.min(rectOne.x + rectOne.width, rectTwo.x + rectTwo.width) - Math.max(rectOne.x, rectTwo.x),
|
|
2342
|
+
height: Math.min(rectOne.y + rectOne.height, rectTwo.y + rectTwo.height) - Math.max(rectOne.y, rectTwo.y)
|
|
2343
|
+
};
|
|
2344
|
+
}
|
|
2345
|
+
|
|
2266
2346
|
exports.Panel = Panel;
|
|
2267
2347
|
exports.PanelGroup = PanelGroup;
|
|
2268
2348
|
exports.PanelResizeHandle = PanelResizeHandle;
|
|
2269
2349
|
exports.assert = assert;
|
|
2350
|
+
exports.getIntersectingRectangle = getIntersectingRectangle;
|
|
2270
2351
|
exports.getPanelElement = getPanelElement;
|
|
2271
2352
|
exports.getPanelElementsForGroup = getPanelElementsForGroup;
|
|
2272
2353
|
exports.getPanelGroupElement = getPanelGroupElement;
|
|
@@ -2274,3 +2355,4 @@ exports.getResizeHandleElement = getResizeHandleElement;
|
|
|
2274
2355
|
exports.getResizeHandleElementIndex = getResizeHandleElementIndex;
|
|
2275
2356
|
exports.getResizeHandleElementsForGroup = getResizeHandleElementsForGroup;
|
|
2276
2357
|
exports.getResizeHandlePanelIds = getResizeHandlePanelIds;
|
|
2358
|
+
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.development.cjs.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { compare } from 'stacking-order';
|
|
2
3
|
|
|
3
4
|
const isBrowser = typeof window !== "undefined";
|
|
4
5
|
|
|
@@ -283,6 +284,14 @@ function getInputType() {
|
|
|
283
284
|
}
|
|
284
285
|
}
|
|
285
286
|
|
|
287
|
+
function intersects(rectOne, rectTwo, strict) {
|
|
288
|
+
if (strict) {
|
|
289
|
+
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;
|
|
290
|
+
} else {
|
|
291
|
+
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;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
286
295
|
const EXCEEDED_HORIZONTAL_MIN = 0b0001;
|
|
287
296
|
const EXCEEDED_HORIZONTAL_MAX = 0b0010;
|
|
288
297
|
const EXCEEDED_VERTICAL_MIN = 0b0100;
|
|
@@ -321,12 +330,16 @@ function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins
|
|
|
321
330
|
};
|
|
322
331
|
}
|
|
323
332
|
function handlePointerDown(event) {
|
|
333
|
+
const {
|
|
334
|
+
target
|
|
335
|
+
} = event;
|
|
324
336
|
const {
|
|
325
337
|
x,
|
|
326
338
|
y
|
|
327
339
|
} = getResizeEventCoordinates(event);
|
|
328
340
|
isPointerDown = true;
|
|
329
341
|
recalculateIntersectingHandles({
|
|
342
|
+
target,
|
|
330
343
|
x,
|
|
331
344
|
y
|
|
332
345
|
});
|
|
@@ -341,29 +354,32 @@ function handlePointerMove(event) {
|
|
|
341
354
|
x,
|
|
342
355
|
y
|
|
343
356
|
} = getResizeEventCoordinates(event);
|
|
344
|
-
if (isPointerDown) {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
} = data;
|
|
349
|
-
setResizeHandlerState("move", "drag", event);
|
|
350
|
-
});
|
|
357
|
+
if (!isPointerDown) {
|
|
358
|
+
const {
|
|
359
|
+
target
|
|
360
|
+
} = event;
|
|
351
361
|
|
|
352
|
-
//
|
|
353
|
-
|
|
354
|
-
|
|
362
|
+
// Recalculate intersecting handles whenever the pointer moves, except if it has already been pressed
|
|
363
|
+
// at that point, the handles may not move with the pointer (depending on constraints)
|
|
364
|
+
// but the same set of active handles should be locked until the pointer is released
|
|
355
365
|
recalculateIntersectingHandles({
|
|
366
|
+
target,
|
|
356
367
|
x,
|
|
357
368
|
y
|
|
358
369
|
});
|
|
359
|
-
updateResizeHandlerStates("move", event);
|
|
360
|
-
updateCursor();
|
|
361
370
|
}
|
|
371
|
+
updateResizeHandlerStates("move", event);
|
|
372
|
+
|
|
373
|
+
// Update cursor based on return value(s) from active handles
|
|
374
|
+
updateCursor();
|
|
362
375
|
if (intersectingHandles.length > 0) {
|
|
363
376
|
event.preventDefault();
|
|
364
377
|
}
|
|
365
378
|
}
|
|
366
379
|
function handlePointerUp(event) {
|
|
380
|
+
const {
|
|
381
|
+
target
|
|
382
|
+
} = event;
|
|
367
383
|
const {
|
|
368
384
|
x,
|
|
369
385
|
y
|
|
@@ -373,33 +389,72 @@ function handlePointerUp(event) {
|
|
|
373
389
|
if (intersectingHandles.length > 0) {
|
|
374
390
|
event.preventDefault();
|
|
375
391
|
}
|
|
392
|
+
updateResizeHandlerStates("up", event);
|
|
376
393
|
recalculateIntersectingHandles({
|
|
394
|
+
target,
|
|
377
395
|
x,
|
|
378
396
|
y
|
|
379
397
|
});
|
|
380
|
-
updateResizeHandlerStates("up", event);
|
|
381
398
|
updateCursor();
|
|
382
399
|
updateListeners();
|
|
383
400
|
}
|
|
384
401
|
function recalculateIntersectingHandles({
|
|
402
|
+
target,
|
|
385
403
|
x,
|
|
386
404
|
y
|
|
387
405
|
}) {
|
|
388
406
|
intersectingHandles.splice(0);
|
|
407
|
+
let targetElement = null;
|
|
408
|
+
if (target instanceof HTMLElement) {
|
|
409
|
+
targetElement = target;
|
|
410
|
+
}
|
|
389
411
|
registeredResizeHandlers.forEach(data => {
|
|
390
412
|
const {
|
|
391
|
-
element,
|
|
413
|
+
element: dragHandleElement,
|
|
392
414
|
hitAreaMargins
|
|
393
415
|
} = data;
|
|
416
|
+
const dragHandleRect = dragHandleElement.getBoundingClientRect();
|
|
394
417
|
const {
|
|
395
418
|
bottom,
|
|
396
419
|
left,
|
|
397
420
|
right,
|
|
398
421
|
top
|
|
399
|
-
} =
|
|
422
|
+
} = dragHandleRect;
|
|
400
423
|
const margin = isCoarsePointer ? hitAreaMargins.coarse : hitAreaMargins.fine;
|
|
401
|
-
const
|
|
402
|
-
if (
|
|
424
|
+
const eventIntersects = x >= left - margin && x <= right + margin && y >= top - margin && y <= bottom + margin;
|
|
425
|
+
if (eventIntersects) {
|
|
426
|
+
// TRICKY
|
|
427
|
+
// We listen for pointers events at the root in order to support hit area margins
|
|
428
|
+
// (determining when the pointer is close enough to an element to be considered a "hit")
|
|
429
|
+
// Clicking on an element "above" a handle (e.g. a modal) should prevent a hit though
|
|
430
|
+
// so at this point we need to compare stacking order of a potentially intersecting drag handle,
|
|
431
|
+
// and the element that was actually clicked/touched
|
|
432
|
+
if (targetElement !== null && dragHandleElement !== targetElement && !dragHandleElement.contains(targetElement) && !targetElement.contains(dragHandleElement) &&
|
|
433
|
+
// Calculating stacking order has a cost, so we should avoid it if possible
|
|
434
|
+
// That is why we only check potentially intersecting handles,
|
|
435
|
+
// and why we skip if the event target is within the handle's DOM
|
|
436
|
+
compare(targetElement, dragHandleElement) > 0) {
|
|
437
|
+
// If the target is above the drag handle, then we also need to confirm they overlap
|
|
438
|
+
// If they are beside each other (e.g. a panel and its drag handle) then the handle is still interactive
|
|
439
|
+
//
|
|
440
|
+
// It's not enough to compare only the target
|
|
441
|
+
// The target might be a small element inside of a larger container
|
|
442
|
+
// (For example, a SPAN or a DIV inside of a larger modal dialog)
|
|
443
|
+
let currentElement = targetElement;
|
|
444
|
+
let didIntersect = false;
|
|
445
|
+
while (currentElement) {
|
|
446
|
+
if (currentElement.contains(dragHandleElement)) {
|
|
447
|
+
break;
|
|
448
|
+
} else if (intersects(currentElement.getBoundingClientRect(), dragHandleRect, true)) {
|
|
449
|
+
didIntersect = true;
|
|
450
|
+
break;
|
|
451
|
+
}
|
|
452
|
+
currentElement = currentElement.parentElement;
|
|
453
|
+
}
|
|
454
|
+
if (didIntersect) {
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
403
458
|
intersectingHandles.push(data);
|
|
404
459
|
}
|
|
405
460
|
});
|
|
@@ -491,15 +546,8 @@ function updateResizeHandlerStates(action, event) {
|
|
|
491
546
|
const {
|
|
492
547
|
setResizeHandlerState
|
|
493
548
|
} = data;
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
setResizeHandlerState(action, "drag", event);
|
|
497
|
-
} else {
|
|
498
|
-
setResizeHandlerState(action, "hover", event);
|
|
499
|
-
}
|
|
500
|
-
} else {
|
|
501
|
-
setResizeHandlerState(action, "inactive", event);
|
|
502
|
-
}
|
|
549
|
+
const isActive = intersectingHandles.includes(data);
|
|
550
|
+
setResizeHandlerState(action, isActive, event);
|
|
503
551
|
});
|
|
504
552
|
}
|
|
505
553
|
|
|
@@ -2136,6 +2184,12 @@ function PanelResizeHandle({
|
|
|
2136
2184
|
const [state, setState] = useState("inactive");
|
|
2137
2185
|
const [isFocused, setIsFocused] = useState(false);
|
|
2138
2186
|
const [resizeHandler, setResizeHandler] = useState(null);
|
|
2187
|
+
const committedValuesRef = useRef({
|
|
2188
|
+
state
|
|
2189
|
+
});
|
|
2190
|
+
useLayoutEffect(() => {
|
|
2191
|
+
committedValuesRef.current.state = state;
|
|
2192
|
+
});
|
|
2139
2193
|
useEffect(() => {
|
|
2140
2194
|
if (disabled) {
|
|
2141
2195
|
setResizeHandler(null);
|
|
@@ -2151,38 +2205,47 @@ function PanelResizeHandle({
|
|
|
2151
2205
|
}
|
|
2152
2206
|
const element = elementRef.current;
|
|
2153
2207
|
assert(element);
|
|
2154
|
-
const setResizeHandlerState = (action,
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
onDragging
|
|
2208
|
+
const setResizeHandlerState = (action, isActive, event) => {
|
|
2209
|
+
if (isActive) {
|
|
2210
|
+
switch (action) {
|
|
2211
|
+
case "down":
|
|
2212
|
+
{
|
|
2213
|
+
setState("drag");
|
|
2214
|
+
startDragging(resizeHandleId, event);
|
|
2215
|
+
const {
|
|
2216
|
+
onDragging
|
|
2217
|
+
} = callbacksRef.current;
|
|
2218
|
+
if (onDragging) {
|
|
2219
|
+
onDragging(true);
|
|
2220
|
+
}
|
|
2221
|
+
break;
|
|
2165
2222
|
}
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2223
|
+
case "move":
|
|
2224
|
+
{
|
|
2225
|
+
const {
|
|
2226
|
+
state
|
|
2227
|
+
} = committedValuesRef.current;
|
|
2228
|
+
if (state !== "drag") {
|
|
2229
|
+
setState("hover");
|
|
2230
|
+
}
|
|
2231
|
+
resizeHandler(event);
|
|
2232
|
+
break;
|
|
2176
2233
|
}
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2234
|
+
case "up":
|
|
2235
|
+
{
|
|
2236
|
+
setState("hover");
|
|
2237
|
+
stopDragging();
|
|
2238
|
+
const {
|
|
2239
|
+
onDragging
|
|
2240
|
+
} = callbacksRef.current;
|
|
2241
|
+
if (onDragging) {
|
|
2242
|
+
onDragging(false);
|
|
2243
|
+
}
|
|
2244
|
+
break;
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
} else {
|
|
2248
|
+
setState("inactive");
|
|
2186
2249
|
}
|
|
2187
2250
|
};
|
|
2188
2251
|
return registerResizeHandle(resizeHandleId, element, direction, {
|
|
@@ -2239,4 +2302,21 @@ function getPanelElementsForGroup(groupId, scope = document) {
|
|
|
2239
2302
|
return Array.from(scope.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
2240
2303
|
}
|
|
2241
2304
|
|
|
2242
|
-
|
|
2305
|
+
function getIntersectingRectangle(rectOne, rectTwo, strict) {
|
|
2306
|
+
if (!intersects(rectOne, rectTwo, strict)) {
|
|
2307
|
+
return {
|
|
2308
|
+
x: 0,
|
|
2309
|
+
y: 0,
|
|
2310
|
+
width: 0,
|
|
2311
|
+
height: 0
|
|
2312
|
+
};
|
|
2313
|
+
}
|
|
2314
|
+
return {
|
|
2315
|
+
x: Math.max(rectOne.x, rectTwo.x),
|
|
2316
|
+
y: Math.max(rectOne.y, rectTwo.y),
|
|
2317
|
+
width: Math.min(rectOne.x + rectOne.width, rectTwo.x + rectTwo.width) - Math.max(rectOne.x, rectTwo.x),
|
|
2318
|
+
height: Math.min(rectOne.y + rectOne.height, rectTwo.y + rectTwo.height) - Math.max(rectOne.y, rectTwo.y)
|
|
2319
|
+
};
|
|
2320
|
+
}
|
|
2321
|
+
|
|
2322
|
+
export { Panel, PanelGroup, PanelResizeHandle, assert, getIntersectingRectangle, getPanelElement, getPanelElementsForGroup, getPanelGroupElement, getResizeHandleElement, getResizeHandleElementIndex, getResizeHandleElementsForGroup, getResizeHandlePanelIds, intersects };
|