react-resizable-panels 2.1.8 → 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.
@@ -6,6 +6,22 @@ import { createContext, useRef, forwardRef, createElement, useContext, useImpera
6
6
  const PanelGroupContext = createContext(null);
7
7
  PanelGroupContext.displayName = "PanelGroupContext";
8
8
 
9
+ const DATA_ATTRIBUTES = {
10
+ group: "data-panel-group",
11
+ groupDirection: "data-panel-group-direction",
12
+ groupId: "data-panel-group-id",
13
+ panel: "data-panel",
14
+ panelCollapsible: "data-panel-collapsible",
15
+ panelId: "data-panel-id",
16
+ panelSize: "data-panel-size",
17
+ resizeHandle: "data-resize-handle",
18
+ resizeHandleActive: "data-resize-handle-active",
19
+ resizeHandleEnabled: "data-panel-resize-handle-enabled",
20
+ resizeHandleId: "data-panel-resize-handle-id",
21
+ resizeHandleState: "data-resize-handle-state"
22
+ };
23
+ const PRECISION = 10;
24
+
9
25
  const useId = React["useId".toString()];
10
26
  const wrappedUseId = typeof useId === "function" ? useId : () => null;
11
27
  let counter = 0;
@@ -107,11 +123,11 @@ function PanelWithForwardedRef({
107
123
  ...styleFromProps
108
124
  },
109
125
  // CSS selectors
110
- "data-panel": "",
111
- "data-panel-collapsible": collapsible || undefined,
112
- "data-panel-group-id": groupId,
113
- "data-panel-id": panelId,
114
- "data-panel-size": parseFloat("" + style.flexGrow).toFixed(1)
126
+ [DATA_ATTRIBUTES.groupId]: groupId,
127
+ [DATA_ATTRIBUTES.panel]: "",
128
+ [DATA_ATTRIBUTES.panelCollapsible]: collapsible || undefined,
129
+ [DATA_ATTRIBUTES.panelId]: panelId,
130
+ [DATA_ATTRIBUTES.panelSize]: parseFloat("" + style.flexGrow).toFixed(1)
115
131
  });
116
132
  }
117
133
  const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
@@ -131,6 +147,7 @@ function setNonce(value) {
131
147
 
132
148
  let currentCursorStyle = null;
133
149
  let enabled = true;
150
+ let prevRuleIndex = -1;
134
151
  let styleElement = null;
135
152
  function disableGlobalCursorStyles() {
136
153
  enabled = false;
@@ -180,9 +197,11 @@ function resetGlobalCursorStyle() {
180
197
  document.head.removeChild(styleElement);
181
198
  currentCursorStyle = null;
182
199
  styleElement = null;
200
+ prevRuleIndex = -1;
183
201
  }
184
202
  }
185
203
  function setGlobalCursorStyle(state, constraintFlags) {
204
+ var _styleElement$sheet$i, _styleElement$sheet2;
186
205
  if (!enabled) {
187
206
  return;
188
207
  }
@@ -199,7 +218,11 @@ function setGlobalCursorStyle(state, constraintFlags) {
199
218
  }
200
219
  document.head.appendChild(styleElement);
201
220
  }
202
- styleElement.innerHTML = `*{cursor: ${style}!important;}`;
221
+ if (prevRuleIndex >= 0) {
222
+ var _styleElement$sheet;
223
+ (_styleElement$sheet = styleElement.sheet) === null || _styleElement$sheet === void 0 ? void 0 : _styleElement$sheet.removeRule(prevRuleIndex);
224
+ }
225
+ 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;
203
226
  }
204
227
 
205
228
  function isKeyDown(event) {
@@ -430,7 +453,9 @@ function handlePointerDown(event) {
430
453
  if (intersectingHandles.length > 0) {
431
454
  updateResizeHandlerStates("down", event);
432
455
  event.preventDefault();
433
- event.stopPropagation();
456
+ if (!isWithinResizeHandle(target)) {
457
+ event.stopImmediatePropagation();
458
+ }
434
459
  }
435
460
  }
436
461
  function handlePointerMove(event) {
@@ -479,6 +504,9 @@ function handlePointerUp(event) {
479
504
  isPointerDown = false;
480
505
  if (intersectingHandles.length > 0) {
481
506
  event.preventDefault();
507
+ if (!isWithinResizeHandle(target)) {
508
+ event.stopImmediatePropagation();
509
+ }
482
510
  }
483
511
  updateResizeHandlerStates("up", event);
484
512
  recalculateIntersectingHandles({
@@ -489,6 +517,16 @@ function handlePointerUp(event) {
489
517
  updateCursor();
490
518
  updateListeners();
491
519
  }
520
+ function isWithinResizeHandle(element) {
521
+ let currentElement = element;
522
+ while (currentElement) {
523
+ if (currentElement.hasAttribute(DATA_ATTRIBUTES.resizeHandle)) {
524
+ return true;
525
+ }
526
+ currentElement = currentElement.parentElement;
527
+ }
528
+ return false;
529
+ }
492
530
  function recalculateIntersectingHandles({
493
531
  target,
494
532
  x,
@@ -580,49 +618,42 @@ function updateCursor() {
580
618
  resetGlobalCursorStyle();
581
619
  }
582
620
  }
621
+ let listenersAbortController = new AbortController();
583
622
  function updateListeners() {
584
- ownerDocumentCounts.forEach((_, ownerDocument) => {
585
- const {
586
- body
587
- } = ownerDocument;
588
- body.removeEventListener("contextmenu", handlePointerUp);
589
- body.removeEventListener("pointerdown", handlePointerDown, {
590
- capture: true
591
- });
592
- body.removeEventListener("pointerleave", handlePointerMove);
593
- body.removeEventListener("pointermove", handlePointerMove);
594
- });
595
- window.removeEventListener("pointerup", handlePointerUp);
596
- window.removeEventListener("pointercancel", handlePointerUp);
597
- if (registeredResizeHandlers.size > 0) {
598
- if (isPointerDown) {
599
- if (intersectingHandles.length > 0) {
600
- ownerDocumentCounts.forEach((count, ownerDocument) => {
601
- const {
602
- body
603
- } = ownerDocument;
604
- if (count > 0) {
605
- body.addEventListener("contextmenu", handlePointerUp);
606
- body.addEventListener("pointerleave", handlePointerMove);
607
- body.addEventListener("pointermove", handlePointerMove);
608
- }
609
- });
610
- }
611
- window.addEventListener("pointerup", handlePointerUp);
612
- window.addEventListener("pointercancel", handlePointerUp);
613
- } else {
623
+ listenersAbortController.abort();
624
+ listenersAbortController = new AbortController();
625
+ const options = {
626
+ capture: true,
627
+ signal: listenersAbortController.signal
628
+ };
629
+ if (!registeredResizeHandlers.size) {
630
+ return;
631
+ }
632
+ if (isPointerDown) {
633
+ if (intersectingHandles.length > 0) {
614
634
  ownerDocumentCounts.forEach((count, ownerDocument) => {
615
635
  const {
616
636
  body
617
637
  } = ownerDocument;
618
638
  if (count > 0) {
619
- body.addEventListener("pointerdown", handlePointerDown, {
620
- capture: true
621
- });
622
- body.addEventListener("pointermove", handlePointerMove);
639
+ body.addEventListener("contextmenu", handlePointerUp, options);
640
+ body.addEventListener("pointerleave", handlePointerMove, options);
641
+ body.addEventListener("pointermove", handlePointerMove, options);
623
642
  }
624
643
  });
625
644
  }
645
+ window.addEventListener("pointerup", handlePointerUp, options);
646
+ window.addEventListener("pointercancel", handlePointerUp, options);
647
+ } else {
648
+ ownerDocumentCounts.forEach((count, ownerDocument) => {
649
+ const {
650
+ body
651
+ } = ownerDocument;
652
+ if (count > 0) {
653
+ body.addEventListener("pointerdown", handlePointerDown, options);
654
+ body.addEventListener("pointermove", handlePointerMove, options);
655
+ }
656
+ });
626
657
  }
627
658
  }
628
659
  function updateResizeHandlerStates(action, event) {
@@ -647,8 +678,6 @@ function assert(expectedCondition, message) {
647
678
  }
648
679
  }
649
680
 
650
- const PRECISION = 10;
651
-
652
681
  function fuzzyCompareNumbers(actual, expected, fractionDigits = PRECISION) {
653
682
  if (actual.toFixed(fractionDigits) === expected.toFixed(fractionDigits)) {
654
683
  return 0;
@@ -953,12 +982,12 @@ function adjustLayoutByDelta({
953
982
  }
954
983
 
955
984
  function getResizeHandleElementsForGroup(groupId, scope = document) {
956
- return Array.from(scope.querySelectorAll(`[data-panel-resize-handle-id][data-panel-group-id="${groupId}"]`));
985
+ return Array.from(scope.querySelectorAll(`[${DATA_ATTRIBUTES.resizeHandleId}][data-panel-group-id="${groupId}"]`));
957
986
  }
958
987
 
959
988
  function getResizeHandleElementIndex(groupId, id, scope = document) {
960
989
  const handles = getResizeHandleElementsForGroup(groupId, scope);
961
- const index = handles.findIndex(handle => handle.getAttribute("data-panel-resize-handle-id") === id);
990
+ const index = handles.findIndex(handle => handle.getAttribute(DATA_ATTRIBUTES.resizeHandleId) === id);
962
991
  return index !== null && index !== void 0 ? index : null;
963
992
  }
964
993
 
@@ -983,7 +1012,7 @@ function getPanelGroupElement(id, rootElement = document) {
983
1012
  }
984
1013
 
985
1014
  function getResizeHandleElement(id, scope = document) {
986
- const element = scope.querySelector(`[data-panel-resize-handle-id="${id}"]`);
1015
+ const element = scope.querySelector(`[${DATA_ATTRIBUTES.resizeHandleId}="${id}"]`);
987
1016
  if (element) {
988
1017
  return element;
989
1018
  }
@@ -1028,7 +1057,7 @@ function useWindowSplitterPanelGroupBehavior({
1028
1057
  const handles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
1029
1058
  assert(handles, `No resize handles found for group id "${groupId}"`);
1030
1059
  const cleanupFunctions = handles.map(handle => {
1031
- const handleId = handle.getAttribute("data-panel-resize-handle-id");
1060
+ const handleId = handle.getAttribute(DATA_ATTRIBUTES.resizeHandleId);
1032
1061
  assert(handleId, `Resize handle element has no handle id attribute`);
1033
1062
  const [idBefore, idAfter] = getResizeHandlePanelIds(groupId, handleId, panelDataArray, panelGroupElement);
1034
1063
  if (idBefore == null || idAfter == null) {
@@ -1106,7 +1135,7 @@ function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDr
1106
1135
  const isHorizontal = direction === "horizontal";
1107
1136
  const handleElement = getResizeHandleElement(dragHandleId, panelGroupElement);
1108
1137
  assert(handleElement, `No resize handle element found for id "${dragHandleId}"`);
1109
- const groupId = handleElement.getAttribute("data-panel-group-id");
1138
+ const groupId = handleElement.getAttribute(DATA_ATTRIBUTES.groupId);
1110
1139
  assert(groupId, `Resize handle element has no group id attribute`);
1111
1140
  let {
1112
1141
  initialCursorPosition
@@ -1911,9 +1940,9 @@ function PanelGroupWithForwardedRef({
1911
1940
  ...styleFromProps
1912
1941
  },
1913
1942
  // CSS selectors
1914
- "data-panel-group": "",
1915
- "data-panel-group-direction": direction,
1916
- "data-panel-group-id": groupId
1943
+ [DATA_ATTRIBUTES.group]: "",
1944
+ [DATA_ATTRIBUTES.groupDirection]: direction,
1945
+ [DATA_ATTRIBUTES.groupId]: groupId
1917
1946
  }));
1918
1947
  }
1919
1948
  const PanelGroup = forwardRef((props, ref) => createElement(PanelGroupWithForwardedRef, {
@@ -1972,7 +2001,7 @@ function useWindowSplitterResizeHandlerBehavior({
1972
2001
  case "F6":
1973
2002
  {
1974
2003
  event.preventDefault();
1975
- const groupId = handleElement.getAttribute("data-panel-group-id");
2004
+ const groupId = handleElement.getAttribute(DATA_ATTRIBUTES.groupId);
1976
2005
  assert(groupId, `No group element found for id "${groupId}"`);
1977
2006
  const handles = getResizeHandleElementsForGroup(groupId, panelGroupElement);
1978
2007
  const index = getResizeHandleElementIndex(groupId, handleId, panelGroupElement);
@@ -2064,54 +2093,54 @@ function PanelResizeHandle({
2064
2093
  assert(element, "Element ref not attached");
2065
2094
  let didMove = false;
2066
2095
  const setResizeHandlerState = (action, isActive, event) => {
2067
- if (isActive) {
2068
- switch (action) {
2069
- case "down":
2070
- {
2071
- setState("drag");
2072
- didMove = false;
2073
- assert(event, 'Expected event to be defined for "down" action');
2074
- startDragging(resizeHandleId, event);
2075
- const {
2076
- onDragging,
2077
- onPointerDown
2078
- } = callbacksRef.current;
2079
- onDragging === null || onDragging === void 0 ? void 0 : onDragging(true);
2080
- onPointerDown === null || onPointerDown === void 0 ? void 0 : onPointerDown();
2081
- break;
2082
- }
2083
- case "move":
2084
- {
2085
- const {
2086
- state
2087
- } = committedValuesRef.current;
2088
- didMove = true;
2089
- if (state !== "drag") {
2090
- setState("hover");
2091
- }
2092
- assert(event, 'Expected event to be defined for "move" action');
2093
- resizeHandler(event);
2094
- break;
2095
- }
2096
- case "up":
2097
- {
2096
+ if (!isActive) {
2097
+ setState("inactive");
2098
+ return;
2099
+ }
2100
+ switch (action) {
2101
+ case "down":
2102
+ {
2103
+ setState("drag");
2104
+ didMove = false;
2105
+ assert(event, 'Expected event to be defined for "down" action');
2106
+ startDragging(resizeHandleId, event);
2107
+ const {
2108
+ onDragging,
2109
+ onPointerDown
2110
+ } = callbacksRef.current;
2111
+ onDragging === null || onDragging === void 0 ? void 0 : onDragging(true);
2112
+ onPointerDown === null || onPointerDown === void 0 ? void 0 : onPointerDown();
2113
+ break;
2114
+ }
2115
+ case "move":
2116
+ {
2117
+ const {
2118
+ state
2119
+ } = committedValuesRef.current;
2120
+ didMove = true;
2121
+ if (state !== "drag") {
2098
2122
  setState("hover");
2099
- stopDragging();
2100
- const {
2101
- onClick,
2102
- onDragging,
2103
- onPointerUp
2104
- } = callbacksRef.current;
2105
- onDragging === null || onDragging === void 0 ? void 0 : onDragging(false);
2106
- onPointerUp === null || onPointerUp === void 0 ? void 0 : onPointerUp();
2107
- if (!didMove) {
2108
- onClick === null || onClick === void 0 ? void 0 : onClick();
2109
- }
2110
- break;
2111
2123
  }
2112
- }
2113
- } else {
2114
- setState("inactive");
2124
+ assert(event, 'Expected event to be defined for "move" action');
2125
+ resizeHandler(event);
2126
+ break;
2127
+ }
2128
+ case "up":
2129
+ {
2130
+ setState("hover");
2131
+ stopDragging();
2132
+ const {
2133
+ onClick,
2134
+ onDragging,
2135
+ onPointerUp
2136
+ } = callbacksRef.current;
2137
+ onDragging === null || onDragging === void 0 ? void 0 : onDragging(false);
2138
+ onPointerUp === null || onPointerUp === void 0 ? void 0 : onPointerUp();
2139
+ if (!didMove) {
2140
+ onClick === null || onClick === void 0 ? void 0 : onClick();
2141
+ }
2142
+ break;
2143
+ }
2115
2144
  }
2116
2145
  };
2117
2146
  return registerResizeHandle(resizeHandleId, element, direction, {
@@ -2150,13 +2179,13 @@ function PanelResizeHandle({
2150
2179
  },
2151
2180
  tabIndex,
2152
2181
  // CSS selectors
2153
- "data-panel-group-direction": direction,
2154
- "data-panel-group-id": groupId,
2155
- "data-resize-handle": "",
2156
- "data-resize-handle-active": state === "drag" ? "pointer" : isFocused ? "keyboard" : undefined,
2157
- "data-resize-handle-state": state,
2158
- "data-panel-resize-handle-enabled": !disabled,
2159
- "data-panel-resize-handle-id": resizeHandleId
2182
+ [DATA_ATTRIBUTES.groupDirection]: direction,
2183
+ [DATA_ATTRIBUTES.groupId]: groupId,
2184
+ [DATA_ATTRIBUTES.resizeHandle]: "",
2185
+ [DATA_ATTRIBUTES.resizeHandleActive]: state === "drag" ? "pointer" : isFocused ? "keyboard" : undefined,
2186
+ [DATA_ATTRIBUTES.resizeHandleEnabled]: !disabled,
2187
+ [DATA_ATTRIBUTES.resizeHandleId]: resizeHandleId,
2188
+ [DATA_ATTRIBUTES.resizeHandleState]: state
2160
2189
  });
2161
2190
  }
2162
2191
  PanelResizeHandle.displayName = "PanelResizeHandle";
@@ -2190,4 +2219,4 @@ function getIntersectingRectangle(rectOne, rectTwo, strict) {
2190
2219
  };
2191
2220
  }
2192
2221
 
2193
- export { Panel, PanelGroup, PanelResizeHandle, assert, disableGlobalCursorStyles, enableGlobalCursorStyles, getIntersectingRectangle, getPanelElement, getPanelElementsForGroup, getPanelGroupElement, getResizeHandleElement, getResizeHandleElementIndex, getResizeHandleElementsForGroup, getResizeHandlePanelIds, intersects, setNonce };
2222
+ export { DATA_ATTRIBUTES, Panel, PanelGroup, PanelResizeHandle, assert, disableGlobalCursorStyles, enableGlobalCursorStyles, getIntersectingRectangle, getPanelElement, getPanelElementsForGroup, getPanelGroupElement, getResizeHandleElement, getResizeHandleElementIndex, getResizeHandleElementsForGroup, getResizeHandlePanelIds, intersects, setNonce };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-resizable-panels",
3
- "version": "2.1.8",
3
+ "version": "2.1.9",
4
4
  "description": "React components for resizable panel groups/layouts",
5
5
  "author": "Brian Vaughn <brian.david.vaughn@gmail.com>",
6
6
  "license": "MIT",
@@ -66,15 +66,6 @@
66
66
  }
67
67
  },
68
68
  "types": "dist/react-resizable-panels.cjs.d.ts",
69
- "scripts": {
70
- "clear": "pnpm run clear:builds & pnpm run clear:node_modules",
71
- "clear:builds": "rm -rf ./packages/*/dist",
72
- "clear:node_modules": "rm -rf ./node_modules",
73
- "lint": "eslint \"src/**/*.{ts,tsx}\"",
74
- "test": "jest --config=jest.config.js",
75
- "test:watch": "jest --config=jest.config.js --watch",
76
- "watch": "parcel watch --port=2345"
77
- },
78
69
  "devDependencies": {
79
70
  "@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6",
80
71
  "@babel/plugin-proposal-optional-chaining": "7.21.0",
@@ -91,5 +82,14 @@
91
82
  },
92
83
  "browserslist": [
93
84
  "Chrome 79"
94
- ]
95
- }
85
+ ],
86
+ "scripts": {
87
+ "clear": "pnpm run clear:builds & pnpm run clear:node_modules",
88
+ "clear:builds": "rm -rf ./packages/*/dist",
89
+ "clear:node_modules": "rm -rf ./node_modules",
90
+ "lint": "eslint \"src/**/*.{ts,tsx}\"",
91
+ "test": "jest --config=jest.config.js",
92
+ "test:watch": "jest --config=jest.config.js --watch",
93
+ "watch": "parcel watch --port=2345"
94
+ }
95
+ }