react-resizable-panels 2.1.7 → 2.1.9

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 (27) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +4 -0
  3. package/dist/declarations/src/Panel.d.ts +1 -1
  4. package/dist/declarations/src/PanelGroup.d.ts +1 -1
  5. package/dist/declarations/src/PanelResizeHandle.d.ts +6 -3
  6. package/dist/declarations/src/constants.d.ts +15 -0
  7. package/dist/declarations/src/index.d.ts +3 -2
  8. package/dist/react-resizable-panels.browser.cjs.js +202 -176
  9. package/dist/react-resizable-panels.browser.cjs.mjs +1 -0
  10. package/dist/react-resizable-panels.browser.development.cjs.js +202 -176
  11. package/dist/react-resizable-panels.browser.development.cjs.mjs +1 -0
  12. package/dist/react-resizable-panels.browser.development.esm.js +150 -124
  13. package/dist/react-resizable-panels.browser.esm.js +150 -124
  14. package/dist/react-resizable-panels.cjs.js +202 -176
  15. package/dist/react-resizable-panels.cjs.mjs +1 -0
  16. package/dist/react-resizable-panels.development.cjs.js +202 -176
  17. package/dist/react-resizable-panels.development.cjs.mjs +1 -0
  18. package/dist/react-resizable-panels.development.esm.js +150 -124
  19. package/dist/react-resizable-panels.development.node.cjs.js +201 -174
  20. package/dist/react-resizable-panels.development.node.cjs.mjs +1 -0
  21. package/dist/react-resizable-panels.development.node.esm.js +149 -122
  22. package/dist/react-resizable-panels.esm.js +150 -124
  23. package/dist/react-resizable-panels.node.cjs.js +201 -174
  24. package/dist/react-resizable-panels.node.cjs.mjs +1 -0
  25. package/dist/react-resizable-panels.node.esm.js +149 -122
  26. package/package.json +12 -13
  27. package/dist/declarations/src/vendor/react.d.ts +0 -7
@@ -1,37 +1,32 @@
1
1
  import * as React from 'react';
2
+ import { createContext, useLayoutEffect, useRef, forwardRef, createElement, useContext, useImperativeHandle, useState, useCallback, useEffect, useMemo } from 'react';
2
3
 
3
4
  const isBrowser = typeof window !== "undefined";
4
5
 
5
- // This module exists to work around Webpack issue https://github.com/webpack/webpack/issues/14814
6
-
7
- // eslint-disable-next-line no-restricted-imports
8
-
9
- const {
10
- createElement,
11
- createContext,
12
- createRef,
13
- forwardRef,
14
- useCallback,
15
- useContext,
16
- useEffect,
17
- useImperativeHandle,
18
- useLayoutEffect,
19
- useMemo,
20
- useRef,
21
- useState
22
- } = React;
23
-
24
- // `Math.random()` and `.slice(0, 5)` prevents bundlers from trying to `import { useId } from 'react'`
25
- const useId = React[`useId${Math.random()}`.slice(0, 5)];
26
- const useLayoutEffect_do_not_use_directly = useLayoutEffect;
27
-
28
6
  // The "contextmenu" event is not supported as a PointerEvent in all browsers yet, so MouseEvent still need to be handled
29
7
 
30
8
  const PanelGroupContext = createContext(null);
31
9
  PanelGroupContext.displayName = "PanelGroupContext";
32
10
 
33
- const useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect_do_not_use_directly : () => {};
11
+ const DATA_ATTRIBUTES = {
12
+ group: "data-panel-group",
13
+ groupDirection: "data-panel-group-direction",
14
+ groupId: "data-panel-group-id",
15
+ panel: "data-panel",
16
+ panelCollapsible: "data-panel-collapsible",
17
+ panelId: "data-panel-id",
18
+ panelSize: "data-panel-size",
19
+ resizeHandle: "data-resize-handle",
20
+ resizeHandleActive: "data-resize-handle-active",
21
+ resizeHandleEnabled: "data-panel-resize-handle-enabled",
22
+ resizeHandleId: "data-panel-resize-handle-id",
23
+ resizeHandleState: "data-resize-handle-state"
24
+ };
25
+ const PRECISION = 10;
26
+
27
+ const useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : () => {};
34
28
 
29
+ const useId = React["useId".toString()];
35
30
  const wrappedUseId = typeof useId === "function" ? useId : () => null;
36
31
  let counter = 0;
37
32
  function useUniqueId(idFromParams = null) {
@@ -159,17 +154,17 @@ function PanelWithForwardedRef({
159
154
  ...rest,
160
155
  children,
161
156
  className: classNameFromProps,
162
- id: idFromProps,
157
+ id: panelId,
163
158
  style: {
164
159
  ...style,
165
160
  ...styleFromProps
166
161
  },
167
162
  // CSS selectors
168
- "data-panel": "",
169
- "data-panel-collapsible": collapsible || undefined,
170
- "data-panel-group-id": groupId,
171
- "data-panel-id": panelId,
172
- "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
163
+ [DATA_ATTRIBUTES.groupId]: groupId,
164
+ [DATA_ATTRIBUTES.panel]: "",
165
+ [DATA_ATTRIBUTES.panelCollapsible]: collapsible || undefined,
166
+ [DATA_ATTRIBUTES.panelId]: panelId,
167
+ [DATA_ATTRIBUTES.panelSize]: parseFloat("" + style.flexGrow).toFixed(1)
173
168
  });
174
169
  }
175
170
  const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
@@ -189,6 +184,7 @@ function setNonce(value) {
189
184
 
190
185
  let currentCursorStyle = null;
191
186
  let enabled = true;
187
+ let prevRuleIndex = -1;
192
188
  let styleElement = null;
193
189
  function disableGlobalCursorStyles() {
194
190
  enabled = false;
@@ -238,9 +234,11 @@ function resetGlobalCursorStyle() {
238
234
  document.head.removeChild(styleElement);
239
235
  currentCursorStyle = null;
240
236
  styleElement = null;
237
+ prevRuleIndex = -1;
241
238
  }
242
239
  }
243
240
  function setGlobalCursorStyle(state, constraintFlags) {
241
+ var _styleElement$sheet$i, _styleElement$sheet2;
244
242
  if (!enabled) {
245
243
  return;
246
244
  }
@@ -257,7 +255,11 @@ function setGlobalCursorStyle(state, constraintFlags) {
257
255
  }
258
256
  document.head.appendChild(styleElement);
259
257
  }
260
- styleElement.innerHTML = `*{cursor: ${style}!important;}`;
258
+ if (prevRuleIndex >= 0) {
259
+ var _styleElement$sheet;
260
+ (_styleElement$sheet = styleElement.sheet) === null || _styleElement$sheet === void 0 ? void 0 : _styleElement$sheet.removeRule(prevRuleIndex);
261
+ }
262
+ prevRuleIndex = (_styleElement$sheet$i = (_styleElement$sheet2 = styleElement.sheet) === null || _styleElement$sheet2 === void 0 ? void 0 : _styleElement$sheet2.insertRule(`*{cursor: ${style} !important;}`)) !== null && _styleElement$sheet$i !== void 0 ? _styleElement$sheet$i : -1;
261
263
  }
262
264
 
263
265
  function isKeyDown(event) {
@@ -488,7 +490,9 @@ function handlePointerDown(event) {
488
490
  if (intersectingHandles.length > 0) {
489
491
  updateResizeHandlerStates("down", event);
490
492
  event.preventDefault();
491
- event.stopPropagation();
493
+ if (!isWithinResizeHandle(target)) {
494
+ event.stopImmediatePropagation();
495
+ }
492
496
  }
493
497
  }
494
498
  function handlePointerMove(event) {
@@ -537,6 +541,9 @@ function handlePointerUp(event) {
537
541
  isPointerDown = false;
538
542
  if (intersectingHandles.length > 0) {
539
543
  event.preventDefault();
544
+ if (!isWithinResizeHandle(target)) {
545
+ event.stopImmediatePropagation();
546
+ }
540
547
  }
541
548
  updateResizeHandlerStates("up", event);
542
549
  recalculateIntersectingHandles({
@@ -547,6 +554,16 @@ function handlePointerUp(event) {
547
554
  updateCursor();
548
555
  updateListeners();
549
556
  }
557
+ function isWithinResizeHandle(element) {
558
+ let currentElement = element;
559
+ while (currentElement) {
560
+ if (currentElement.hasAttribute(DATA_ATTRIBUTES.resizeHandle)) {
561
+ return true;
562
+ }
563
+ currentElement = currentElement.parentElement;
564
+ }
565
+ return false;
566
+ }
550
567
  function recalculateIntersectingHandles({
551
568
  target,
552
569
  x,
@@ -638,47 +655,42 @@ function updateCursor() {
638
655
  resetGlobalCursorStyle();
639
656
  }
640
657
  }
658
+ let listenersAbortController = new AbortController();
641
659
  function updateListeners() {
642
- ownerDocumentCounts.forEach((_, ownerDocument) => {
643
- const {
644
- body
645
- } = ownerDocument;
646
- body.removeEventListener("contextmenu", handlePointerUp);
647
- body.removeEventListener("pointerdown", handlePointerDown);
648
- body.removeEventListener("pointerleave", handlePointerMove);
649
- body.removeEventListener("pointermove", handlePointerMove);
650
- });
651
- window.removeEventListener("pointerup", handlePointerUp);
652
- window.removeEventListener("pointercancel", handlePointerUp);
653
- if (registeredResizeHandlers.size > 0) {
654
- if (isPointerDown) {
655
- if (intersectingHandles.length > 0) {
656
- ownerDocumentCounts.forEach((count, ownerDocument) => {
657
- const {
658
- body
659
- } = ownerDocument;
660
- if (count > 0) {
661
- body.addEventListener("contextmenu", handlePointerUp);
662
- body.addEventListener("pointerleave", handlePointerMove);
663
- body.addEventListener("pointermove", handlePointerMove);
664
- }
665
- });
666
- }
667
- window.addEventListener("pointerup", handlePointerUp);
668
- window.addEventListener("pointercancel", handlePointerUp);
669
- } else {
660
+ listenersAbortController.abort();
661
+ listenersAbortController = new AbortController();
662
+ const options = {
663
+ capture: true,
664
+ signal: listenersAbortController.signal
665
+ };
666
+ if (!registeredResizeHandlers.size) {
667
+ return;
668
+ }
669
+ if (isPointerDown) {
670
+ if (intersectingHandles.length > 0) {
670
671
  ownerDocumentCounts.forEach((count, ownerDocument) => {
671
672
  const {
672
673
  body
673
674
  } = ownerDocument;
674
675
  if (count > 0) {
675
- body.addEventListener("pointerdown", handlePointerDown, {
676
- capture: true
677
- });
678
- body.addEventListener("pointermove", handlePointerMove);
676
+ body.addEventListener("contextmenu", handlePointerUp, options);
677
+ body.addEventListener("pointerleave", handlePointerMove, options);
678
+ body.addEventListener("pointermove", handlePointerMove, options);
679
679
  }
680
680
  });
681
681
  }
682
+ window.addEventListener("pointerup", handlePointerUp, options);
683
+ window.addEventListener("pointercancel", handlePointerUp, options);
684
+ } else {
685
+ ownerDocumentCounts.forEach((count, ownerDocument) => {
686
+ const {
687
+ body
688
+ } = ownerDocument;
689
+ if (count > 0) {
690
+ body.addEventListener("pointerdown", handlePointerDown, options);
691
+ body.addEventListener("pointermove", handlePointerMove, options);
692
+ }
693
+ });
682
694
  }
683
695
  }
684
696
  function updateResizeHandlerStates(action, event) {
@@ -703,8 +715,6 @@ function assert(expectedCondition, message) {
703
715
  }
704
716
  }
705
717
 
706
- const PRECISION = 10;
707
-
708
718
  function fuzzyCompareNumbers(actual, expected, fractionDigits = PRECISION) {
709
719
  if (actual.toFixed(fractionDigits) === expected.toFixed(fractionDigits)) {
710
720
  return 0;
@@ -1048,12 +1058,12 @@ function calculateAriaValues({
1048
1058
  }
1049
1059
 
1050
1060
  function getResizeHandleElementsForGroup(groupId, scope = document) {
1051
- return Array.from(scope.querySelectorAll(`[data-panel-resize-handle-id][data-panel-group-id="${groupId}"]`));
1061
+ return Array.from(scope.querySelectorAll(`[${DATA_ATTRIBUTES.resizeHandleId}][data-panel-group-id="${groupId}"]`));
1052
1062
  }
1053
1063
 
1054
1064
  function getResizeHandleElementIndex(groupId, id, scope = document) {
1055
1065
  const handles = getResizeHandleElementsForGroup(groupId, scope);
1056
- const index = handles.findIndex(handle => handle.getAttribute("data-panel-resize-handle-id") === id);
1066
+ const index = handles.findIndex(handle => handle.getAttribute(DATA_ATTRIBUTES.resizeHandleId) === id);
1057
1067
  return index !== null && index !== void 0 ? index : null;
1058
1068
  }
1059
1069
 
@@ -1078,7 +1088,7 @@ function getPanelGroupElement(id, rootElement = document) {
1078
1088
  }
1079
1089
 
1080
1090
  function getResizeHandleElement(id, scope = document) {
1081
- const element = scope.querySelector(`[data-panel-resize-handle-id="${id}"]`);
1091
+ const element = scope.querySelector(`[${DATA_ATTRIBUTES.resizeHandleId}="${id}"]`);
1082
1092
  if (element) {
1083
1093
  return element;
1084
1094
  }
@@ -1157,7 +1167,7 @@ function useWindowSplitterPanelGroupBehavior({
1157
1167
  const handles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
1158
1168
  assert(handles, `No resize handles found for group id "${groupId}"`);
1159
1169
  const cleanupFunctions = handles.map(handle => {
1160
- const handleId = handle.getAttribute("data-panel-resize-handle-id");
1170
+ const handleId = handle.getAttribute(DATA_ATTRIBUTES.resizeHandleId);
1161
1171
  assert(handleId, `Resize handle element has no handle id attribute`);
1162
1172
  const [idBefore, idAfter] = getResizeHandlePanelIds(groupId, handleId, panelDataArray, panelGroupElement);
1163
1173
  if (idBefore == null || idAfter == null) {
@@ -1235,7 +1245,7 @@ function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDr
1235
1245
  const isHorizontal = direction === "horizontal";
1236
1246
  const handleElement = getResizeHandleElement(dragHandleId, panelGroupElement);
1237
1247
  assert(handleElement, `No resize handle element found for id "${dragHandleId}"`);
1238
- const groupId = handleElement.getAttribute("data-panel-group-id");
1248
+ const groupId = handleElement.getAttribute(DATA_ATTRIBUTES.groupId);
1239
1249
  assert(groupId, `Resize handle element has no group id attribute`);
1240
1250
  let {
1241
1251
  initialCursorPosition
@@ -2151,9 +2161,9 @@ function PanelGroupWithForwardedRef({
2151
2161
  ...styleFromProps
2152
2162
  },
2153
2163
  // CSS selectors
2154
- "data-panel-group": "",
2155
- "data-panel-group-direction": direction,
2156
- "data-panel-group-id": groupId
2164
+ [DATA_ATTRIBUTES.group]: "",
2165
+ [DATA_ATTRIBUTES.groupDirection]: direction,
2166
+ [DATA_ATTRIBUTES.groupId]: groupId
2157
2167
  }));
2158
2168
  }
2159
2169
  const PanelGroup = forwardRef((props, ref) => createElement(PanelGroupWithForwardedRef, {
@@ -2212,7 +2222,7 @@ function useWindowSplitterResizeHandlerBehavior({
2212
2222
  case "F6":
2213
2223
  {
2214
2224
  event.preventDefault();
2215
- const groupId = handleElement.getAttribute("data-panel-group-id");
2225
+ const groupId = handleElement.getAttribute(DATA_ATTRIBUTES.groupId);
2216
2226
  assert(groupId, `No group element found for id "${groupId}"`);
2217
2227
  const handles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
2218
2228
  const index = getResizeHandleElementIndex(groupId, handleId, panelGroupElement);
@@ -2238,8 +2248,11 @@ function PanelResizeHandle({
2238
2248
  hitAreaMargins,
2239
2249
  id: idFromProps,
2240
2250
  onBlur,
2251
+ onClick,
2241
2252
  onDragging,
2242
2253
  onFocus,
2254
+ onPointerDown,
2255
+ onPointerUp,
2243
2256
  style: styleFromProps = {},
2244
2257
  tabIndex = 0,
2245
2258
  tagName: Type = "div",
@@ -2250,10 +2263,16 @@ function PanelResizeHandle({
2250
2263
 
2251
2264
  // Use a ref to guard against users passing inline props
2252
2265
  const callbacksRef = useRef({
2253
- onDragging
2266
+ onClick,
2267
+ onDragging,
2268
+ onPointerDown,
2269
+ onPointerUp
2254
2270
  });
2255
2271
  useEffect(() => {
2272
+ callbacksRef.current.onClick = onClick;
2256
2273
  callbacksRef.current.onDragging = onDragging;
2274
+ callbacksRef.current.onPointerDown = onPointerDown;
2275
+ callbacksRef.current.onPointerUp = onPointerUp;
2257
2276
  });
2258
2277
  const panelGroupContext = useContext(PanelGroupContext);
2259
2278
  if (panelGroupContext === null) {
@@ -2296,49 +2315,56 @@ function PanelResizeHandle({
2296
2315
  }
2297
2316
  const element = elementRef.current;
2298
2317
  assert(element, "Element ref not attached");
2318
+ let didMove = false;
2299
2319
  const setResizeHandlerState = (action, isActive, event) => {
2300
- if (isActive) {
2301
- switch (action) {
2302
- case "down":
2303
- {
2304
- setState("drag");
2305
- assert(event, 'Expected event to be defined for "down" action');
2306
- startDragging(resizeHandleId, event);
2307
- const {
2308
- onDragging
2309
- } = callbacksRef.current;
2310
- if (onDragging) {
2311
- onDragging(true);
2312
- }
2313
- break;
2314
- }
2315
- case "move":
2316
- {
2317
- const {
2318
- state
2319
- } = committedValuesRef.current;
2320
- if (state !== "drag") {
2321
- setState("hover");
2322
- }
2323
- assert(event, 'Expected event to be defined for "move" action');
2324
- resizeHandler(event);
2325
- break;
2326
- }
2327
- case "up":
2328
- {
2320
+ if (!isActive) {
2321
+ setState("inactive");
2322
+ return;
2323
+ }
2324
+ switch (action) {
2325
+ case "down":
2326
+ {
2327
+ setState("drag");
2328
+ didMove = false;
2329
+ assert(event, 'Expected event to be defined for "down" action');
2330
+ startDragging(resizeHandleId, event);
2331
+ const {
2332
+ onDragging,
2333
+ onPointerDown
2334
+ } = callbacksRef.current;
2335
+ onDragging === null || onDragging === void 0 ? void 0 : onDragging(true);
2336
+ onPointerDown === null || onPointerDown === void 0 ? void 0 : onPointerDown();
2337
+ break;
2338
+ }
2339
+ case "move":
2340
+ {
2341
+ const {
2342
+ state
2343
+ } = committedValuesRef.current;
2344
+ didMove = true;
2345
+ if (state !== "drag") {
2329
2346
  setState("hover");
2330
- stopDragging();
2331
- const {
2332
- onDragging
2333
- } = callbacksRef.current;
2334
- if (onDragging) {
2335
- onDragging(false);
2336
- }
2337
- break;
2338
2347
  }
2339
- }
2340
- } else {
2341
- setState("inactive");
2348
+ assert(event, 'Expected event to be defined for "move" action');
2349
+ resizeHandler(event);
2350
+ break;
2351
+ }
2352
+ case "up":
2353
+ {
2354
+ setState("hover");
2355
+ stopDragging();
2356
+ const {
2357
+ onClick,
2358
+ onDragging,
2359
+ onPointerUp
2360
+ } = callbacksRef.current;
2361
+ onDragging === null || onDragging === void 0 ? void 0 : onDragging(false);
2362
+ onPointerUp === null || onPointerUp === void 0 ? void 0 : onPointerUp();
2363
+ if (!didMove) {
2364
+ onClick === null || onClick === void 0 ? void 0 : onClick();
2365
+ }
2366
+ break;
2367
+ }
2342
2368
  }
2343
2369
  };
2344
2370
  return registerResizeHandle(resizeHandleId, element, direction, {
@@ -2377,13 +2403,13 @@ function PanelResizeHandle({
2377
2403
  },
2378
2404
  tabIndex,
2379
2405
  // CSS selectors
2380
- "data-panel-group-direction": direction,
2381
- "data-panel-group-id": groupId,
2382
- "data-resize-handle": "",
2383
- "data-resize-handle-active": state === "drag" ? "pointer" : isFocused ? "keyboard" : undefined,
2384
- "data-resize-handle-state": state,
2385
- "data-panel-resize-handle-enabled": !disabled,
2386
- "data-panel-resize-handle-id": resizeHandleId
2406
+ [DATA_ATTRIBUTES.groupDirection]: direction,
2407
+ [DATA_ATTRIBUTES.groupId]: groupId,
2408
+ [DATA_ATTRIBUTES.resizeHandle]: "",
2409
+ [DATA_ATTRIBUTES.resizeHandleActive]: state === "drag" ? "pointer" : isFocused ? "keyboard" : undefined,
2410
+ [DATA_ATTRIBUTES.resizeHandleEnabled]: !disabled,
2411
+ [DATA_ATTRIBUTES.resizeHandleId]: resizeHandleId,
2412
+ [DATA_ATTRIBUTES.resizeHandleState]: state
2387
2413
  });
2388
2414
  }
2389
2415
  PanelResizeHandle.displayName = "PanelResizeHandle";
@@ -2417,4 +2443,4 @@ function getIntersectingRectangle(rectOne, rectTwo, strict) {
2417
2443
  };
2418
2444
  }
2419
2445
 
2420
- export { Panel, PanelGroup, PanelResizeHandle, assert, disableGlobalCursorStyles, enableGlobalCursorStyles, getIntersectingRectangle, getPanelElement, getPanelElementsForGroup, getPanelGroupElement, getResizeHandleElement, getResizeHandleElementIndex, getResizeHandleElementsForGroup, getResizeHandlePanelIds, intersects, setNonce };
2446
+ export { DATA_ATTRIBUTES, Panel, PanelGroup, PanelResizeHandle, assert, disableGlobalCursorStyles, enableGlobalCursorStyles, getIntersectingRectangle, getPanelElement, getPanelElementsForGroup, getPanelGroupElement, getResizeHandleElement, getResizeHandleElementIndex, getResizeHandleElementsForGroup, getResizeHandlePanelIds, intersects, setNonce };