react-resizable-panels 2.0.4 → 2.0.6

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 (35) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/declarations/src/index.d.ts +3 -1
  3. package/dist/declarations/src/utils/rects/getIntersectingRectangle.d.ts +2 -0
  4. package/dist/declarations/src/utils/rects/intersects.d.ts +2 -0
  5. package/dist/declarations/src/utils/rects/types.d.ts +6 -0
  6. package/dist/declarations/src/vendor/react.d.ts +3 -2
  7. package/dist/react-resizable-panels.browser.cjs.js +87 -7
  8. package/dist/react-resizable-panels.browser.cjs.mjs +3 -1
  9. package/dist/react-resizable-panels.browser.development.cjs.js +87 -7
  10. package/dist/react-resizable-panels.browser.development.cjs.mjs +3 -1
  11. package/dist/react-resizable-panels.browser.development.esm.js +86 -8
  12. package/dist/react-resizable-panels.browser.esm.js +86 -8
  13. package/dist/react-resizable-panels.cjs.js +87 -7
  14. package/dist/react-resizable-panels.cjs.mjs +3 -1
  15. package/dist/react-resizable-panels.development.cjs.js +87 -7
  16. package/dist/react-resizable-panels.development.cjs.mjs +3 -1
  17. package/dist/react-resizable-panels.development.esm.js +86 -8
  18. package/dist/react-resizable-panels.development.node.cjs.js +84 -8
  19. package/dist/react-resizable-panels.development.node.cjs.mjs +3 -1
  20. package/dist/react-resizable-panels.development.node.esm.js +83 -9
  21. package/dist/react-resizable-panels.esm.js +86 -8
  22. package/dist/react-resizable-panels.node.cjs.js +84 -8
  23. package/dist/react-resizable-panels.node.cjs.mjs +3 -1
  24. package/dist/react-resizable-panels.node.esm.js +83 -9
  25. package/package.json +4 -1
  26. package/src/PanelResizeHandle.ts +2 -2
  27. package/src/PanelResizeHandleRegistry.ts +75 -8
  28. package/src/hooks/useIsomorphicEffect.ts +4 -2
  29. package/src/index.ts +4 -0
  30. package/src/utils/rects/getIntersectingRectangle.test.ts +198 -0
  31. package/src/utils/rects/getIntersectingRectangle.ts +28 -0
  32. package/src/utils/rects/intersects.test.ts +197 -0
  33. package/src/utils/rects/intersects.ts +23 -0
  34. package/src/utils/rects/types.ts +6 -0
  35. package/src/vendor/react.ts +3 -1
@@ -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
 
@@ -23,11 +24,12 @@ const {
23
24
 
24
25
  // `toString()` prevents bundlers from trying to `import { useId } from 'react'`
25
26
  const useId = React["useId".toString()];
27
+ const useLayoutEffect_do_not_use_directly = useLayoutEffect;
26
28
 
27
29
  const PanelGroupContext = createContext(null);
28
30
  PanelGroupContext.displayName = "PanelGroupContext";
29
31
 
30
- const useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : () => {};
32
+ const useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect_do_not_use_directly : () => {};
31
33
 
32
34
  const wrappedUseId = typeof useId === "function" ? useId : () => null;
33
35
  let counter = 0;
@@ -283,6 +285,14 @@ function getInputType() {
283
285
  }
284
286
  }
285
287
 
288
+ function intersects(rectOne, rectTwo, strict) {
289
+ if (strict) {
290
+ 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;
291
+ } else {
292
+ 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;
293
+ }
294
+ }
295
+
286
296
  const EXCEEDED_HORIZONTAL_MIN = 0b0001;
287
297
  const EXCEEDED_HORIZONTAL_MAX = 0b0010;
288
298
  const EXCEEDED_VERTICAL_MIN = 0b0100;
@@ -321,12 +331,16 @@ function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins
321
331
  };
322
332
  }
323
333
  function handlePointerDown(event) {
334
+ const {
335
+ target
336
+ } = event;
324
337
  const {
325
338
  x,
326
339
  y
327
340
  } = getResizeEventCoordinates(event);
328
341
  isPointerDown = true;
329
342
  recalculateIntersectingHandles({
343
+ target,
330
344
  x,
331
345
  y
332
346
  });
@@ -342,10 +356,15 @@ function handlePointerMove(event) {
342
356
  y
343
357
  } = getResizeEventCoordinates(event);
344
358
  if (!isPointerDown) {
359
+ const {
360
+ target
361
+ } = event;
362
+
345
363
  // Recalculate intersecting handles whenever the pointer moves, except if it has already been pressed
346
364
  // at that point, the handles may not move with the pointer (depending on constraints)
347
365
  // but the same set of active handles should be locked until the pointer is released
348
366
  recalculateIntersectingHandles({
367
+ target,
349
368
  x,
350
369
  y
351
370
  });
@@ -359,6 +378,9 @@ function handlePointerMove(event) {
359
378
  }
360
379
  }
361
380
  function handlePointerUp(event) {
381
+ const {
382
+ target
383
+ } = event;
362
384
  const {
363
385
  x,
364
386
  y
@@ -368,33 +390,72 @@ function handlePointerUp(event) {
368
390
  if (intersectingHandles.length > 0) {
369
391
  event.preventDefault();
370
392
  }
393
+ updateResizeHandlerStates("up", event);
371
394
  recalculateIntersectingHandles({
395
+ target,
372
396
  x,
373
397
  y
374
398
  });
375
- updateResizeHandlerStates("up", event);
376
399
  updateCursor();
377
400
  updateListeners();
378
401
  }
379
402
  function recalculateIntersectingHandles({
403
+ target,
380
404
  x,
381
405
  y
382
406
  }) {
383
407
  intersectingHandles.splice(0);
408
+ let targetElement = null;
409
+ if (target instanceof HTMLElement) {
410
+ targetElement = target;
411
+ }
384
412
  registeredResizeHandlers.forEach(data => {
385
413
  const {
386
- element,
414
+ element: dragHandleElement,
387
415
  hitAreaMargins
388
416
  } = data;
417
+ const dragHandleRect = dragHandleElement.getBoundingClientRect();
389
418
  const {
390
419
  bottom,
391
420
  left,
392
421
  right,
393
422
  top
394
- } = element.getBoundingClientRect();
423
+ } = dragHandleRect;
395
424
  const margin = isCoarsePointer ? hitAreaMargins.coarse : hitAreaMargins.fine;
396
- const intersects = x >= left - margin && x <= right + margin && y >= top - margin && y <= bottom + margin;
397
- if (intersects) {
425
+ const eventIntersects = x >= left - margin && x <= right + margin && y >= top - margin && y <= bottom + margin;
426
+ if (eventIntersects) {
427
+ // TRICKY
428
+ // We listen for pointers events at the root in order to support hit area margins
429
+ // (determining when the pointer is close enough to an element to be considered a "hit")
430
+ // Clicking on an element "above" a handle (e.g. a modal) should prevent a hit though
431
+ // so at this point we need to compare stacking order of a potentially intersecting drag handle,
432
+ // and the element that was actually clicked/touched
433
+ if (targetElement !== null && dragHandleElement !== targetElement && !dragHandleElement.contains(targetElement) && !targetElement.contains(dragHandleElement) &&
434
+ // Calculating stacking order has a cost, so we should avoid it if possible
435
+ // That is why we only check potentially intersecting handles,
436
+ // and why we skip if the event target is within the handle's DOM
437
+ compare(targetElement, dragHandleElement) > 0) {
438
+ // If the target is above the drag handle, then we also need to confirm they overlap
439
+ // If they are beside each other (e.g. a panel and its drag handle) then the handle is still interactive
440
+ //
441
+ // It's not enough to compare only the target
442
+ // The target might be a small element inside of a larger container
443
+ // (For example, a SPAN or a DIV inside of a larger modal dialog)
444
+ let currentElement = targetElement;
445
+ let didIntersect = false;
446
+ while (currentElement) {
447
+ if (currentElement.contains(dragHandleElement)) {
448
+ break;
449
+ } else if (intersects(currentElement.getBoundingClientRect(), dragHandleRect, true)) {
450
+ didIntersect = true;
451
+ break;
452
+ }
453
+ currentElement = currentElement.parentElement;
454
+ }
455
+ if (didIntersect) {
456
+ return;
457
+ }
458
+ }
398
459
  intersectingHandles.push(data);
399
460
  }
400
461
  });
@@ -2127,7 +2188,7 @@ function PanelResizeHandle({
2127
2188
  const committedValuesRef = useRef({
2128
2189
  state
2129
2190
  });
2130
- useLayoutEffect(() => {
2191
+ useIsomorphicLayoutEffect(() => {
2131
2192
  committedValuesRef.current.state = state;
2132
2193
  });
2133
2194
  useEffect(() => {
@@ -2242,4 +2303,21 @@ function getPanelElementsForGroup(groupId, scope = document) {
2242
2303
  return Array.from(scope.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
2243
2304
  }
2244
2305
 
2245
- export { Panel, PanelGroup, PanelResizeHandle, assert, getPanelElement, getPanelElementsForGroup, getPanelGroupElement, getResizeHandleElement, getResizeHandleElementIndex, getResizeHandleElementsForGroup, getResizeHandlePanelIds };
2306
+ function getIntersectingRectangle(rectOne, rectTwo, strict) {
2307
+ if (!intersects(rectOne, rectTwo, strict)) {
2308
+ return {
2309
+ x: 0,
2310
+ y: 0,
2311
+ width: 0,
2312
+ height: 0
2313
+ };
2314
+ }
2315
+ return {
2316
+ x: Math.max(rectOne.x, rectTwo.x),
2317
+ y: Math.max(rectOne.y, rectTwo.y),
2318
+ width: Math.min(rectOne.x + rectOne.width, rectTwo.x + rectTwo.width) - Math.max(rectOne.x, rectTwo.x),
2319
+ height: Math.min(rectOne.y + rectOne.height, rectTwo.y + rectTwo.height) - Math.max(rectOne.y, rectTwo.y)
2320
+ };
2321
+ }
2322
+
2323
+ export { Panel, PanelGroup, PanelResizeHandle, assert, getIntersectingRectangle, getPanelElement, getPanelElementsForGroup, getPanelGroupElement, getResizeHandleElement, getResizeHandleElementIndex, getResizeHandleElementsForGroup, getResizeHandlePanelIds, intersects };
@@ -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;
@@ -270,6 +271,14 @@ function getInputType() {
270
271
  }
271
272
  }
272
273
 
274
+ function intersects(rectOne, rectTwo, strict) {
275
+ if (strict) {
276
+ 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;
277
+ } else {
278
+ 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;
279
+ }
280
+ }
281
+
273
282
  const EXCEEDED_HORIZONTAL_MIN = 0b0001;
274
283
  const EXCEEDED_HORIZONTAL_MAX = 0b0010;
275
284
  const EXCEEDED_VERTICAL_MIN = 0b0100;
@@ -308,12 +317,16 @@ function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins
308
317
  };
309
318
  }
310
319
  function handlePointerDown(event) {
320
+ const {
321
+ target
322
+ } = event;
311
323
  const {
312
324
  x,
313
325
  y
314
326
  } = getResizeEventCoordinates(event);
315
327
  isPointerDown = true;
316
328
  recalculateIntersectingHandles({
329
+ target,
317
330
  x,
318
331
  y
319
332
  });
@@ -329,10 +342,15 @@ function handlePointerMove(event) {
329
342
  y
330
343
  } = getResizeEventCoordinates(event);
331
344
  if (!isPointerDown) {
345
+ const {
346
+ target
347
+ } = event;
348
+
332
349
  // Recalculate intersecting handles whenever the pointer moves, except if it has already been pressed
333
350
  // at that point, the handles may not move with the pointer (depending on constraints)
334
351
  // but the same set of active handles should be locked until the pointer is released
335
352
  recalculateIntersectingHandles({
353
+ target,
336
354
  x,
337
355
  y
338
356
  });
@@ -346,6 +364,9 @@ function handlePointerMove(event) {
346
364
  }
347
365
  }
348
366
  function handlePointerUp(event) {
367
+ const {
368
+ target
369
+ } = event;
349
370
  const {
350
371
  x,
351
372
  y
@@ -355,33 +376,72 @@ function handlePointerUp(event) {
355
376
  if (intersectingHandles.length > 0) {
356
377
  event.preventDefault();
357
378
  }
379
+ updateResizeHandlerStates("up", event);
358
380
  recalculateIntersectingHandles({
381
+ target,
359
382
  x,
360
383
  y
361
384
  });
362
- updateResizeHandlerStates("up", event);
363
385
  updateCursor();
364
386
  updateListeners();
365
387
  }
366
388
  function recalculateIntersectingHandles({
389
+ target,
367
390
  x,
368
391
  y
369
392
  }) {
370
393
  intersectingHandles.splice(0);
394
+ let targetElement = null;
395
+ if (target instanceof HTMLElement) {
396
+ targetElement = target;
397
+ }
371
398
  registeredResizeHandlers.forEach(data => {
372
399
  const {
373
- element,
400
+ element: dragHandleElement,
374
401
  hitAreaMargins
375
402
  } = data;
403
+ const dragHandleRect = dragHandleElement.getBoundingClientRect();
376
404
  const {
377
405
  bottom,
378
406
  left,
379
407
  right,
380
408
  top
381
- } = element.getBoundingClientRect();
409
+ } = dragHandleRect;
382
410
  const margin = isCoarsePointer ? hitAreaMargins.coarse : hitAreaMargins.fine;
383
- const intersects = x >= left - margin && x <= right + margin && y >= top - margin && y <= bottom + margin;
384
- if (intersects) {
411
+ const eventIntersects = x >= left - margin && x <= right + margin && y >= top - margin && y <= bottom + margin;
412
+ if (eventIntersects) {
413
+ // TRICKY
414
+ // We listen for pointers events at the root in order to support hit area margins
415
+ // (determining when the pointer is close enough to an element to be considered a "hit")
416
+ // Clicking on an element "above" a handle (e.g. a modal) should prevent a hit though
417
+ // so at this point we need to compare stacking order of a potentially intersecting drag handle,
418
+ // and the element that was actually clicked/touched
419
+ if (targetElement !== null && dragHandleElement !== targetElement && !dragHandleElement.contains(targetElement) && !targetElement.contains(dragHandleElement) &&
420
+ // Calculating stacking order has a cost, so we should avoid it if possible
421
+ // That is why we only check potentially intersecting handles,
422
+ // and why we skip if the event target is within the handle's DOM
423
+ stackingOrder.compare(targetElement, dragHandleElement) > 0) {
424
+ // If the target is above the drag handle, then we also need to confirm they overlap
425
+ // If they are beside each other (e.g. a panel and its drag handle) then the handle is still interactive
426
+ //
427
+ // It's not enough to compare only the target
428
+ // The target might be a small element inside of a larger container
429
+ // (For example, a SPAN or a DIV inside of a larger modal dialog)
430
+ let currentElement = targetElement;
431
+ let didIntersect = false;
432
+ while (currentElement) {
433
+ if (currentElement.contains(dragHandleElement)) {
434
+ break;
435
+ } else if (intersects(currentElement.getBoundingClientRect(), dragHandleRect, true)) {
436
+ didIntersect = true;
437
+ break;
438
+ }
439
+ currentElement = currentElement.parentElement;
440
+ }
441
+ if (didIntersect) {
442
+ return;
443
+ }
444
+ }
385
445
  intersectingHandles.push(data);
386
446
  }
387
447
  });
@@ -1920,9 +1980,6 @@ function PanelResizeHandle({
1920
1980
  const committedValuesRef = useRef({
1921
1981
  state
1922
1982
  });
1923
- useLayoutEffect(() => {
1924
- committedValuesRef.current.state = state;
1925
- });
1926
1983
  useEffect(() => {
1927
1984
  if (disabled) {
1928
1985
  setResizeHandler(null);
@@ -2035,10 +2092,28 @@ function getPanelElementsForGroup(groupId, scope = document) {
2035
2092
  return Array.from(scope.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
2036
2093
  }
2037
2094
 
2095
+ function getIntersectingRectangle(rectOne, rectTwo, strict) {
2096
+ if (!intersects(rectOne, rectTwo, strict)) {
2097
+ return {
2098
+ x: 0,
2099
+ y: 0,
2100
+ width: 0,
2101
+ height: 0
2102
+ };
2103
+ }
2104
+ return {
2105
+ x: Math.max(rectOne.x, rectTwo.x),
2106
+ y: Math.max(rectOne.y, rectTwo.y),
2107
+ width: Math.min(rectOne.x + rectOne.width, rectTwo.x + rectTwo.width) - Math.max(rectOne.x, rectTwo.x),
2108
+ height: Math.min(rectOne.y + rectOne.height, rectTwo.y + rectTwo.height) - Math.max(rectOne.y, rectTwo.y)
2109
+ };
2110
+ }
2111
+
2038
2112
  exports.Panel = Panel;
2039
2113
  exports.PanelGroup = PanelGroup;
2040
2114
  exports.PanelResizeHandle = PanelResizeHandle;
2041
2115
  exports.assert = assert;
2116
+ exports.getIntersectingRectangle = getIntersectingRectangle;
2042
2117
  exports.getPanelElement = getPanelElement;
2043
2118
  exports.getPanelElementsForGroup = getPanelElementsForGroup;
2044
2119
  exports.getPanelGroupElement = getPanelGroupElement;
@@ -2046,3 +2121,4 @@ exports.getResizeHandleElement = getResizeHandleElement;
2046
2121
  exports.getResizeHandleElementIndex = getResizeHandleElementIndex;
2047
2122
  exports.getResizeHandleElementsForGroup = getResizeHandleElementsForGroup;
2048
2123
  exports.getResizeHandlePanelIds = getResizeHandlePanelIds;
2124
+ 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.node.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
 
@@ -246,6 +247,14 @@ function getInputType() {
246
247
  }
247
248
  }
248
249
 
250
+ function intersects(rectOne, rectTwo, strict) {
251
+ if (strict) {
252
+ 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;
253
+ } else {
254
+ 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;
255
+ }
256
+ }
257
+
249
258
  const EXCEEDED_HORIZONTAL_MIN = 0b0001;
250
259
  const EXCEEDED_HORIZONTAL_MAX = 0b0010;
251
260
  const EXCEEDED_VERTICAL_MIN = 0b0100;
@@ -284,12 +293,16 @@ function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins
284
293
  };
285
294
  }
286
295
  function handlePointerDown(event) {
296
+ const {
297
+ target
298
+ } = event;
287
299
  const {
288
300
  x,
289
301
  y
290
302
  } = getResizeEventCoordinates(event);
291
303
  isPointerDown = true;
292
304
  recalculateIntersectingHandles({
305
+ target,
293
306
  x,
294
307
  y
295
308
  });
@@ -305,10 +318,15 @@ function handlePointerMove(event) {
305
318
  y
306
319
  } = getResizeEventCoordinates(event);
307
320
  if (!isPointerDown) {
321
+ const {
322
+ target
323
+ } = event;
324
+
308
325
  // Recalculate intersecting handles whenever the pointer moves, except if it has already been pressed
309
326
  // at that point, the handles may not move with the pointer (depending on constraints)
310
327
  // but the same set of active handles should be locked until the pointer is released
311
328
  recalculateIntersectingHandles({
329
+ target,
312
330
  x,
313
331
  y
314
332
  });
@@ -322,6 +340,9 @@ function handlePointerMove(event) {
322
340
  }
323
341
  }
324
342
  function handlePointerUp(event) {
343
+ const {
344
+ target
345
+ } = event;
325
346
  const {
326
347
  x,
327
348
  y
@@ -331,33 +352,72 @@ function handlePointerUp(event) {
331
352
  if (intersectingHandles.length > 0) {
332
353
  event.preventDefault();
333
354
  }
355
+ updateResizeHandlerStates("up", event);
334
356
  recalculateIntersectingHandles({
357
+ target,
335
358
  x,
336
359
  y
337
360
  });
338
- updateResizeHandlerStates("up", event);
339
361
  updateCursor();
340
362
  updateListeners();
341
363
  }
342
364
  function recalculateIntersectingHandles({
365
+ target,
343
366
  x,
344
367
  y
345
368
  }) {
346
369
  intersectingHandles.splice(0);
370
+ let targetElement = null;
371
+ if (target instanceof HTMLElement) {
372
+ targetElement = target;
373
+ }
347
374
  registeredResizeHandlers.forEach(data => {
348
375
  const {
349
- element,
376
+ element: dragHandleElement,
350
377
  hitAreaMargins
351
378
  } = data;
379
+ const dragHandleRect = dragHandleElement.getBoundingClientRect();
352
380
  const {
353
381
  bottom,
354
382
  left,
355
383
  right,
356
384
  top
357
- } = element.getBoundingClientRect();
385
+ } = dragHandleRect;
358
386
  const margin = isCoarsePointer ? hitAreaMargins.coarse : hitAreaMargins.fine;
359
- const intersects = x >= left - margin && x <= right + margin && y >= top - margin && y <= bottom + margin;
360
- if (intersects) {
387
+ const eventIntersects = x >= left - margin && x <= right + margin && y >= top - margin && y <= bottom + margin;
388
+ if (eventIntersects) {
389
+ // TRICKY
390
+ // We listen for pointers events at the root in order to support hit area margins
391
+ // (determining when the pointer is close enough to an element to be considered a "hit")
392
+ // Clicking on an element "above" a handle (e.g. a modal) should prevent a hit though
393
+ // so at this point we need to compare stacking order of a potentially intersecting drag handle,
394
+ // and the element that was actually clicked/touched
395
+ if (targetElement !== null && dragHandleElement !== targetElement && !dragHandleElement.contains(targetElement) && !targetElement.contains(dragHandleElement) &&
396
+ // Calculating stacking order has a cost, so we should avoid it if possible
397
+ // That is why we only check potentially intersecting handles,
398
+ // and why we skip if the event target is within the handle's DOM
399
+ compare(targetElement, dragHandleElement) > 0) {
400
+ // If the target is above the drag handle, then we also need to confirm they overlap
401
+ // If they are beside each other (e.g. a panel and its drag handle) then the handle is still interactive
402
+ //
403
+ // It's not enough to compare only the target
404
+ // The target might be a small element inside of a larger container
405
+ // (For example, a SPAN or a DIV inside of a larger modal dialog)
406
+ let currentElement = targetElement;
407
+ let didIntersect = false;
408
+ while (currentElement) {
409
+ if (currentElement.contains(dragHandleElement)) {
410
+ break;
411
+ } else if (intersects(currentElement.getBoundingClientRect(), dragHandleRect, true)) {
412
+ didIntersect = true;
413
+ break;
414
+ }
415
+ currentElement = currentElement.parentElement;
416
+ }
417
+ if (didIntersect) {
418
+ return;
419
+ }
420
+ }
361
421
  intersectingHandles.push(data);
362
422
  }
363
423
  });
@@ -1896,9 +1956,6 @@ function PanelResizeHandle({
1896
1956
  const committedValuesRef = useRef({
1897
1957
  state
1898
1958
  });
1899
- useLayoutEffect(() => {
1900
- committedValuesRef.current.state = state;
1901
- });
1902
1959
  useEffect(() => {
1903
1960
  if (disabled) {
1904
1961
  setResizeHandler(null);
@@ -2011,4 +2068,21 @@ function getPanelElementsForGroup(groupId, scope = document) {
2011
2068
  return Array.from(scope.querySelectorAll(`[data-panel][data-panel-group-id="${groupId}"]`));
2012
2069
  }
2013
2070
 
2014
- export { Panel, PanelGroup, PanelResizeHandle, assert, getPanelElement, getPanelElementsForGroup, getPanelGroupElement, getResizeHandleElement, getResizeHandleElementIndex, getResizeHandleElementsForGroup, getResizeHandlePanelIds };
2071
+ function getIntersectingRectangle(rectOne, rectTwo, strict) {
2072
+ if (!intersects(rectOne, rectTwo, strict)) {
2073
+ return {
2074
+ x: 0,
2075
+ y: 0,
2076
+ width: 0,
2077
+ height: 0
2078
+ };
2079
+ }
2080
+ return {
2081
+ x: Math.max(rectOne.x, rectTwo.x),
2082
+ y: Math.max(rectOne.y, rectTwo.y),
2083
+ width: Math.min(rectOne.x + rectOne.width, rectTwo.x + rectTwo.width) - Math.max(rectOne.x, rectTwo.x),
2084
+ height: Math.min(rectOne.y + rectOne.height, rectTwo.y + rectTwo.height) - Math.max(rectOne.y, rectTwo.y)
2085
+ };
2086
+ }
2087
+
2088
+ export { Panel, PanelGroup, PanelResizeHandle, assert, getIntersectingRectangle, getPanelElement, getPanelElementsForGroup, getPanelGroupElement, getResizeHandleElement, getResizeHandleElementIndex, getResizeHandleElementsForGroup, getResizeHandlePanelIds, intersects };