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;
|
|
@@ -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
|
});
|
|
@@ -358,29 +371,32 @@ function handlePointerMove(event) {
|
|
|
358
371
|
x,
|
|
359
372
|
y
|
|
360
373
|
} = getResizeEventCoordinates(event);
|
|
361
|
-
if (isPointerDown) {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
} = data;
|
|
366
|
-
setResizeHandlerState("move", "drag", event);
|
|
367
|
-
});
|
|
374
|
+
if (!isPointerDown) {
|
|
375
|
+
const {
|
|
376
|
+
target
|
|
377
|
+
} = event;
|
|
368
378
|
|
|
369
|
-
//
|
|
370
|
-
|
|
371
|
-
|
|
379
|
+
// Recalculate intersecting handles whenever the pointer moves, except if it has already been pressed
|
|
380
|
+
// at that point, the handles may not move with the pointer (depending on constraints)
|
|
381
|
+
// but the same set of active handles should be locked until the pointer is released
|
|
372
382
|
recalculateIntersectingHandles({
|
|
383
|
+
target,
|
|
373
384
|
x,
|
|
374
385
|
y
|
|
375
386
|
});
|
|
376
|
-
updateResizeHandlerStates("move", event);
|
|
377
|
-
updateCursor();
|
|
378
387
|
}
|
|
388
|
+
updateResizeHandlerStates("move", event);
|
|
389
|
+
|
|
390
|
+
// Update cursor based on return value(s) from active handles
|
|
391
|
+
updateCursor();
|
|
379
392
|
if (intersectingHandles.length > 0) {
|
|
380
393
|
event.preventDefault();
|
|
381
394
|
}
|
|
382
395
|
}
|
|
383
396
|
function handlePointerUp(event) {
|
|
397
|
+
const {
|
|
398
|
+
target
|
|
399
|
+
} = event;
|
|
384
400
|
const {
|
|
385
401
|
x,
|
|
386
402
|
y
|
|
@@ -390,33 +406,72 @@ function handlePointerUp(event) {
|
|
|
390
406
|
if (intersectingHandles.length > 0) {
|
|
391
407
|
event.preventDefault();
|
|
392
408
|
}
|
|
409
|
+
updateResizeHandlerStates("up", event);
|
|
393
410
|
recalculateIntersectingHandles({
|
|
411
|
+
target,
|
|
394
412
|
x,
|
|
395
413
|
y
|
|
396
414
|
});
|
|
397
|
-
updateResizeHandlerStates("up", event);
|
|
398
415
|
updateCursor();
|
|
399
416
|
updateListeners();
|
|
400
417
|
}
|
|
401
418
|
function recalculateIntersectingHandles({
|
|
419
|
+
target,
|
|
402
420
|
x,
|
|
403
421
|
y
|
|
404
422
|
}) {
|
|
405
423
|
intersectingHandles.splice(0);
|
|
424
|
+
let targetElement = null;
|
|
425
|
+
if (target instanceof HTMLElement) {
|
|
426
|
+
targetElement = target;
|
|
427
|
+
}
|
|
406
428
|
registeredResizeHandlers.forEach(data => {
|
|
407
429
|
const {
|
|
408
|
-
element,
|
|
430
|
+
element: dragHandleElement,
|
|
409
431
|
hitAreaMargins
|
|
410
432
|
} = data;
|
|
433
|
+
const dragHandleRect = dragHandleElement.getBoundingClientRect();
|
|
411
434
|
const {
|
|
412
435
|
bottom,
|
|
413
436
|
left,
|
|
414
437
|
right,
|
|
415
438
|
top
|
|
416
|
-
} =
|
|
439
|
+
} = dragHandleRect;
|
|
417
440
|
const margin = isCoarsePointer ? hitAreaMargins.coarse : hitAreaMargins.fine;
|
|
418
|
-
const
|
|
419
|
-
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
|
+
}
|
|
420
475
|
intersectingHandles.push(data);
|
|
421
476
|
}
|
|
422
477
|
});
|
|
@@ -508,15 +563,8 @@ function updateResizeHandlerStates(action, event) {
|
|
|
508
563
|
const {
|
|
509
564
|
setResizeHandlerState
|
|
510
565
|
} = data;
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
setResizeHandlerState(action, "drag", event);
|
|
514
|
-
} else {
|
|
515
|
-
setResizeHandlerState(action, "hover", event);
|
|
516
|
-
}
|
|
517
|
-
} else {
|
|
518
|
-
setResizeHandlerState(action, "inactive", event);
|
|
519
|
-
}
|
|
566
|
+
const isActive = intersectingHandles.includes(data);
|
|
567
|
+
setResizeHandlerState(action, isActive, event);
|
|
520
568
|
});
|
|
521
569
|
}
|
|
522
570
|
|
|
@@ -2153,6 +2201,12 @@ function PanelResizeHandle({
|
|
|
2153
2201
|
const [state, setState] = useState("inactive");
|
|
2154
2202
|
const [isFocused, setIsFocused] = useState(false);
|
|
2155
2203
|
const [resizeHandler, setResizeHandler] = useState(null);
|
|
2204
|
+
const committedValuesRef = useRef({
|
|
2205
|
+
state
|
|
2206
|
+
});
|
|
2207
|
+
useLayoutEffect(() => {
|
|
2208
|
+
committedValuesRef.current.state = state;
|
|
2209
|
+
});
|
|
2156
2210
|
useEffect(() => {
|
|
2157
2211
|
if (disabled) {
|
|
2158
2212
|
setResizeHandler(null);
|
|
@@ -2168,38 +2222,47 @@ function PanelResizeHandle({
|
|
|
2168
2222
|
}
|
|
2169
2223
|
const element = elementRef.current;
|
|
2170
2224
|
assert(element);
|
|
2171
|
-
const setResizeHandlerState = (action,
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
onDragging
|
|
2225
|
+
const setResizeHandlerState = (action, isActive, event) => {
|
|
2226
|
+
if (isActive) {
|
|
2227
|
+
switch (action) {
|
|
2228
|
+
case "down":
|
|
2229
|
+
{
|
|
2230
|
+
setState("drag");
|
|
2231
|
+
startDragging(resizeHandleId, event);
|
|
2232
|
+
const {
|
|
2233
|
+
onDragging
|
|
2234
|
+
} = callbacksRef.current;
|
|
2235
|
+
if (onDragging) {
|
|
2236
|
+
onDragging(true);
|
|
2237
|
+
}
|
|
2238
|
+
break;
|
|
2182
2239
|
}
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2240
|
+
case "move":
|
|
2241
|
+
{
|
|
2242
|
+
const {
|
|
2243
|
+
state
|
|
2244
|
+
} = committedValuesRef.current;
|
|
2245
|
+
if (state !== "drag") {
|
|
2246
|
+
setState("hover");
|
|
2247
|
+
}
|
|
2248
|
+
resizeHandler(event);
|
|
2249
|
+
break;
|
|
2193
2250
|
}
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2251
|
+
case "up":
|
|
2252
|
+
{
|
|
2253
|
+
setState("hover");
|
|
2254
|
+
stopDragging();
|
|
2255
|
+
const {
|
|
2256
|
+
onDragging
|
|
2257
|
+
} = callbacksRef.current;
|
|
2258
|
+
if (onDragging) {
|
|
2259
|
+
onDragging(false);
|
|
2260
|
+
}
|
|
2261
|
+
break;
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
} else {
|
|
2265
|
+
setState("inactive");
|
|
2203
2266
|
}
|
|
2204
2267
|
};
|
|
2205
2268
|
return registerResizeHandle(resizeHandleId, element, direction, {
|
|
@@ -2256,10 +2319,28 @@ function getPanelElementsForGroup(groupId, scope = document) {
|
|
|
2256
2319
|
return Array.from(scope.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
2257
2320
|
}
|
|
2258
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
|
+
|
|
2259
2339
|
exports.Panel = Panel;
|
|
2260
2340
|
exports.PanelGroup = PanelGroup;
|
|
2261
2341
|
exports.PanelResizeHandle = PanelResizeHandle;
|
|
2262
2342
|
exports.assert = assert;
|
|
2343
|
+
exports.getIntersectingRectangle = getIntersectingRectangle;
|
|
2263
2344
|
exports.getPanelElement = getPanelElement;
|
|
2264
2345
|
exports.getPanelElementsForGroup = getPanelElementsForGroup;
|
|
2265
2346
|
exports.getPanelGroupElement = getPanelGroupElement;
|
|
@@ -2267,3 +2348,4 @@ exports.getResizeHandleElement = getResizeHandleElement;
|
|
|
2267
2348
|
exports.getResizeHandleElementIndex = getResizeHandleElementIndex;
|
|
2268
2349
|
exports.getResizeHandleElementsForGroup = getResizeHandleElementsForGroup;
|
|
2269
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
|
});
|
|
@@ -334,29 +347,32 @@ function handlePointerMove(event) {
|
|
|
334
347
|
x,
|
|
335
348
|
y
|
|
336
349
|
} = getResizeEventCoordinates(event);
|
|
337
|
-
if (isPointerDown) {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
} = data;
|
|
342
|
-
setResizeHandlerState("move", "drag", event);
|
|
343
|
-
});
|
|
350
|
+
if (!isPointerDown) {
|
|
351
|
+
const {
|
|
352
|
+
target
|
|
353
|
+
} = event;
|
|
344
354
|
|
|
345
|
-
//
|
|
346
|
-
|
|
347
|
-
|
|
355
|
+
// Recalculate intersecting handles whenever the pointer moves, except if it has already been pressed
|
|
356
|
+
// at that point, the handles may not move with the pointer (depending on constraints)
|
|
357
|
+
// but the same set of active handles should be locked until the pointer is released
|
|
348
358
|
recalculateIntersectingHandles({
|
|
359
|
+
target,
|
|
349
360
|
x,
|
|
350
361
|
y
|
|
351
362
|
});
|
|
352
|
-
updateResizeHandlerStates("move", event);
|
|
353
|
-
updateCursor();
|
|
354
363
|
}
|
|
364
|
+
updateResizeHandlerStates("move", event);
|
|
365
|
+
|
|
366
|
+
// Update cursor based on return value(s) from active handles
|
|
367
|
+
updateCursor();
|
|
355
368
|
if (intersectingHandles.length > 0) {
|
|
356
369
|
event.preventDefault();
|
|
357
370
|
}
|
|
358
371
|
}
|
|
359
372
|
function handlePointerUp(event) {
|
|
373
|
+
const {
|
|
374
|
+
target
|
|
375
|
+
} = event;
|
|
360
376
|
const {
|
|
361
377
|
x,
|
|
362
378
|
y
|
|
@@ -366,33 +382,72 @@ function handlePointerUp(event) {
|
|
|
366
382
|
if (intersectingHandles.length > 0) {
|
|
367
383
|
event.preventDefault();
|
|
368
384
|
}
|
|
385
|
+
updateResizeHandlerStates("up", event);
|
|
369
386
|
recalculateIntersectingHandles({
|
|
387
|
+
target,
|
|
370
388
|
x,
|
|
371
389
|
y
|
|
372
390
|
});
|
|
373
|
-
updateResizeHandlerStates("up", event);
|
|
374
391
|
updateCursor();
|
|
375
392
|
updateListeners();
|
|
376
393
|
}
|
|
377
394
|
function recalculateIntersectingHandles({
|
|
395
|
+
target,
|
|
378
396
|
x,
|
|
379
397
|
y
|
|
380
398
|
}) {
|
|
381
399
|
intersectingHandles.splice(0);
|
|
400
|
+
let targetElement = null;
|
|
401
|
+
if (target instanceof HTMLElement) {
|
|
402
|
+
targetElement = target;
|
|
403
|
+
}
|
|
382
404
|
registeredResizeHandlers.forEach(data => {
|
|
383
405
|
const {
|
|
384
|
-
element,
|
|
406
|
+
element: dragHandleElement,
|
|
385
407
|
hitAreaMargins
|
|
386
408
|
} = data;
|
|
409
|
+
const dragHandleRect = dragHandleElement.getBoundingClientRect();
|
|
387
410
|
const {
|
|
388
411
|
bottom,
|
|
389
412
|
left,
|
|
390
413
|
right,
|
|
391
414
|
top
|
|
392
|
-
} =
|
|
415
|
+
} = dragHandleRect;
|
|
393
416
|
const margin = isCoarsePointer ? hitAreaMargins.coarse : hitAreaMargins.fine;
|
|
394
|
-
const
|
|
395
|
-
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
|
+
}
|
|
396
451
|
intersectingHandles.push(data);
|
|
397
452
|
}
|
|
398
453
|
});
|
|
@@ -484,15 +539,8 @@ function updateResizeHandlerStates(action, event) {
|
|
|
484
539
|
const {
|
|
485
540
|
setResizeHandlerState
|
|
486
541
|
} = data;
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
setResizeHandlerState(action, "drag", event);
|
|
490
|
-
} else {
|
|
491
|
-
setResizeHandlerState(action, "hover", event);
|
|
492
|
-
}
|
|
493
|
-
} else {
|
|
494
|
-
setResizeHandlerState(action, "inactive", event);
|
|
495
|
-
}
|
|
542
|
+
const isActive = intersectingHandles.includes(data);
|
|
543
|
+
setResizeHandlerState(action, isActive, event);
|
|
496
544
|
});
|
|
497
545
|
}
|
|
498
546
|
|
|
@@ -2129,6 +2177,12 @@ function PanelResizeHandle({
|
|
|
2129
2177
|
const [state, setState] = useState("inactive");
|
|
2130
2178
|
const [isFocused, setIsFocused] = useState(false);
|
|
2131
2179
|
const [resizeHandler, setResizeHandler] = useState(null);
|
|
2180
|
+
const committedValuesRef = useRef({
|
|
2181
|
+
state
|
|
2182
|
+
});
|
|
2183
|
+
useLayoutEffect(() => {
|
|
2184
|
+
committedValuesRef.current.state = state;
|
|
2185
|
+
});
|
|
2132
2186
|
useEffect(() => {
|
|
2133
2187
|
if (disabled) {
|
|
2134
2188
|
setResizeHandler(null);
|
|
@@ -2144,38 +2198,47 @@ function PanelResizeHandle({
|
|
|
2144
2198
|
}
|
|
2145
2199
|
const element = elementRef.current;
|
|
2146
2200
|
assert(element);
|
|
2147
|
-
const setResizeHandlerState = (action,
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
onDragging
|
|
2201
|
+
const setResizeHandlerState = (action, isActive, event) => {
|
|
2202
|
+
if (isActive) {
|
|
2203
|
+
switch (action) {
|
|
2204
|
+
case "down":
|
|
2205
|
+
{
|
|
2206
|
+
setState("drag");
|
|
2207
|
+
startDragging(resizeHandleId, event);
|
|
2208
|
+
const {
|
|
2209
|
+
onDragging
|
|
2210
|
+
} = callbacksRef.current;
|
|
2211
|
+
if (onDragging) {
|
|
2212
|
+
onDragging(true);
|
|
2213
|
+
}
|
|
2214
|
+
break;
|
|
2158
2215
|
}
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2216
|
+
case "move":
|
|
2217
|
+
{
|
|
2218
|
+
const {
|
|
2219
|
+
state
|
|
2220
|
+
} = committedValuesRef.current;
|
|
2221
|
+
if (state !== "drag") {
|
|
2222
|
+
setState("hover");
|
|
2223
|
+
}
|
|
2224
|
+
resizeHandler(event);
|
|
2225
|
+
break;
|
|
2169
2226
|
}
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2227
|
+
case "up":
|
|
2228
|
+
{
|
|
2229
|
+
setState("hover");
|
|
2230
|
+
stopDragging();
|
|
2231
|
+
const {
|
|
2232
|
+
onDragging
|
|
2233
|
+
} = callbacksRef.current;
|
|
2234
|
+
if (onDragging) {
|
|
2235
|
+
onDragging(false);
|
|
2236
|
+
}
|
|
2237
|
+
break;
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
} else {
|
|
2241
|
+
setState("inactive");
|
|
2179
2242
|
}
|
|
2180
2243
|
};
|
|
2181
2244
|
return registerResizeHandle(resizeHandleId, element, direction, {
|
|
@@ -2232,4 +2295,21 @@ function getPanelElementsForGroup(groupId, scope = document) {
|
|
|
2232
2295
|
return Array.from(scope.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
|
|
2233
2296
|
}
|
|
2234
2297
|
|
|
2235
|
-
|
|
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 };
|