react-resizable-panels 1.0.9 → 2.0.0
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 +9 -0
- package/README.md +29 -104
- package/dist/declarations/src/PanelResizeHandle.d.ts +3 -1
- package/dist/declarations/src/PanelResizeHandleRegistry.d.ts +20 -0
- package/dist/react-resizable-panels.browser.cjs.js +367 -140
- package/dist/react-resizable-panels.browser.development.cjs.js +367 -140
- package/dist/react-resizable-panels.browser.development.esm.js +367 -140
- package/dist/react-resizable-panels.browser.esm.js +367 -140
- package/dist/react-resizable-panels.cjs.js +367 -140
- package/dist/react-resizable-panels.development.cjs.js +367 -140
- package/dist/react-resizable-panels.development.esm.js +367 -140
- package/dist/react-resizable-panels.development.node.cjs.js +367 -140
- package/dist/react-resizable-panels.development.node.esm.js +367 -140
- package/dist/react-resizable-panels.esm.js +367 -140
- package/dist/react-resizable-panels.node.cjs.js +367 -140
- package/dist/react-resizable-panels.node.esm.js +367 -140
- package/package.json +1 -1
- package/src/Panel.test.tsx +52 -0
- package/src/PanelGroup.ts +23 -16
- package/src/PanelResizeHandle.ts +64 -82
- package/src/PanelResizeHandleRegistry.ts +263 -0
- package/src/utils/calculateDragOffsetPercentage.ts +1 -1
- package/src/utils/cursor.ts +63 -33
- package/src/utils/events/getResizeEventCoordinates.ts +24 -0
- package/src/utils/events/getResizeEventCursorPosition.ts +14 -0
- package/src/utils/{events.ts → events/index.ts} +1 -1
- package/src/utils/getInputType.ts +5 -0
- package/src/utils/getResizeEventCursorPosition.ts +0 -21
|
@@ -139,6 +139,322 @@ const Panel = forwardRef((props, ref) => createElement(PanelWithForwardedRef, {
|
|
|
139
139
|
PanelWithForwardedRef.displayName = "Panel";
|
|
140
140
|
Panel.displayName = "forwardRef(Panel)";
|
|
141
141
|
|
|
142
|
+
let currentCursorStyle = null;
|
|
143
|
+
let styleElement = null;
|
|
144
|
+
function getCursorStyle(state, constraintFlags) {
|
|
145
|
+
if (constraintFlags) {
|
|
146
|
+
const horizontalMin = (constraintFlags & EXCEEDED_HORIZONTAL_MIN) !== 0;
|
|
147
|
+
const horizontalMax = (constraintFlags & EXCEEDED_HORIZONTAL_MAX) !== 0;
|
|
148
|
+
const verticalMin = (constraintFlags & EXCEEDED_VERTICAL_MIN) !== 0;
|
|
149
|
+
const verticalMax = (constraintFlags & EXCEEDED_VERTICAL_MAX) !== 0;
|
|
150
|
+
if (horizontalMin) {
|
|
151
|
+
if (verticalMin) {
|
|
152
|
+
return "se-resize";
|
|
153
|
+
} else if (verticalMax) {
|
|
154
|
+
return "ne-resize";
|
|
155
|
+
} else {
|
|
156
|
+
return "e-resize";
|
|
157
|
+
}
|
|
158
|
+
} else if (horizontalMax) {
|
|
159
|
+
if (verticalMin) {
|
|
160
|
+
return "sw-resize";
|
|
161
|
+
} else if (verticalMax) {
|
|
162
|
+
return "nw-resize";
|
|
163
|
+
} else {
|
|
164
|
+
return "w-resize";
|
|
165
|
+
}
|
|
166
|
+
} else if (verticalMin) {
|
|
167
|
+
return "s-resize";
|
|
168
|
+
} else if (verticalMax) {
|
|
169
|
+
return "n-resize";
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
switch (state) {
|
|
173
|
+
case "horizontal":
|
|
174
|
+
return "ew-resize";
|
|
175
|
+
case "intersection":
|
|
176
|
+
return "move";
|
|
177
|
+
case "vertical":
|
|
178
|
+
return "ns-resize";
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function resetGlobalCursorStyle() {
|
|
182
|
+
if (styleElement !== null) {
|
|
183
|
+
document.head.removeChild(styleElement);
|
|
184
|
+
currentCursorStyle = null;
|
|
185
|
+
styleElement = null;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function setGlobalCursorStyle(state, constraintFlags) {
|
|
189
|
+
const style = getCursorStyle(state, constraintFlags);
|
|
190
|
+
if (currentCursorStyle === style) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
currentCursorStyle = style;
|
|
194
|
+
if (styleElement === null) {
|
|
195
|
+
styleElement = document.createElement("style");
|
|
196
|
+
document.head.appendChild(styleElement);
|
|
197
|
+
}
|
|
198
|
+
styleElement.innerHTML = `*{cursor: ${style}!important;}`;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function isKeyDown(event) {
|
|
202
|
+
return event.type === "keydown";
|
|
203
|
+
}
|
|
204
|
+
function isMouseEvent(event) {
|
|
205
|
+
return event.type.startsWith("mouse");
|
|
206
|
+
}
|
|
207
|
+
function isTouchEvent(event) {
|
|
208
|
+
return event.type.startsWith("touch");
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function getResizeEventCoordinates(event) {
|
|
212
|
+
if (isMouseEvent(event)) {
|
|
213
|
+
return {
|
|
214
|
+
x: event.pageX,
|
|
215
|
+
y: event.pageY
|
|
216
|
+
};
|
|
217
|
+
} else if (isTouchEvent(event)) {
|
|
218
|
+
const touch = event.touches[0];
|
|
219
|
+
if (touch && touch.pageX && touch.pageY) {
|
|
220
|
+
return {
|
|
221
|
+
x: touch.pageX,
|
|
222
|
+
y: touch.pageY
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
x: Infinity,
|
|
228
|
+
y: Infinity
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function getInputType() {
|
|
233
|
+
if (typeof matchMedia === "function") {
|
|
234
|
+
return matchMedia("(pointer:coarse)").matches ? "coarse" : "fine";
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const EXCEEDED_HORIZONTAL_MIN = 0b0001;
|
|
239
|
+
const EXCEEDED_HORIZONTAL_MAX = 0b0010;
|
|
240
|
+
const EXCEEDED_VERTICAL_MIN = 0b0100;
|
|
241
|
+
const EXCEEDED_VERTICAL_MAX = 0b1000;
|
|
242
|
+
const isCoarsePointer = getInputType() === "coarse";
|
|
243
|
+
let intersectingHandles = [];
|
|
244
|
+
let isPointerDown = false;
|
|
245
|
+
let ownerDocumentCounts = new Map();
|
|
246
|
+
let panelConstraintFlags = new Map();
|
|
247
|
+
const registeredResizeHandlers = new Set();
|
|
248
|
+
function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins, setResizeHandlerState) {
|
|
249
|
+
var _ownerDocumentCounts$;
|
|
250
|
+
const {
|
|
251
|
+
ownerDocument
|
|
252
|
+
} = element;
|
|
253
|
+
const data = {
|
|
254
|
+
direction,
|
|
255
|
+
element,
|
|
256
|
+
hitAreaMargins,
|
|
257
|
+
setResizeHandlerState
|
|
258
|
+
};
|
|
259
|
+
const count = (_ownerDocumentCounts$ = ownerDocumentCounts.get(ownerDocument)) !== null && _ownerDocumentCounts$ !== void 0 ? _ownerDocumentCounts$ : 0;
|
|
260
|
+
ownerDocumentCounts.set(ownerDocument, count + 1);
|
|
261
|
+
registeredResizeHandlers.add(data);
|
|
262
|
+
updateListeners();
|
|
263
|
+
return function unregisterResizeHandle() {
|
|
264
|
+
var _ownerDocumentCounts$2;
|
|
265
|
+
panelConstraintFlags.delete(resizeHandleId);
|
|
266
|
+
registeredResizeHandlers.delete(data);
|
|
267
|
+
const count = (_ownerDocumentCounts$2 = ownerDocumentCounts.get(ownerDocument)) !== null && _ownerDocumentCounts$2 !== void 0 ? _ownerDocumentCounts$2 : 1;
|
|
268
|
+
ownerDocumentCounts.set(ownerDocument, count - 1);
|
|
269
|
+
updateListeners();
|
|
270
|
+
if (count === 1) {
|
|
271
|
+
ownerDocumentCounts.delete(ownerDocument);
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
function handlePointerDown(event) {
|
|
276
|
+
const {
|
|
277
|
+
x,
|
|
278
|
+
y
|
|
279
|
+
} = getResizeEventCoordinates(event);
|
|
280
|
+
isPointerDown = true;
|
|
281
|
+
updateResizeHandlerStates("down", event);
|
|
282
|
+
recalculateIntersectingHandles({
|
|
283
|
+
x,
|
|
284
|
+
y
|
|
285
|
+
});
|
|
286
|
+
updateListeners();
|
|
287
|
+
if (intersectingHandles.length > 0) {
|
|
288
|
+
event.preventDefault();
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
function handlePointerMove(event) {
|
|
292
|
+
const {
|
|
293
|
+
x,
|
|
294
|
+
y
|
|
295
|
+
} = getResizeEventCoordinates(event);
|
|
296
|
+
if (isPointerDown) {
|
|
297
|
+
intersectingHandles.forEach(data => {
|
|
298
|
+
const {
|
|
299
|
+
setResizeHandlerState
|
|
300
|
+
} = data;
|
|
301
|
+
setResizeHandlerState("move", "drag", event);
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
// Update cursor based on return value(s) from active handles
|
|
305
|
+
updateCursor();
|
|
306
|
+
} else {
|
|
307
|
+
recalculateIntersectingHandles({
|
|
308
|
+
x,
|
|
309
|
+
y
|
|
310
|
+
});
|
|
311
|
+
updateResizeHandlerStates("move", event);
|
|
312
|
+
updateCursor();
|
|
313
|
+
}
|
|
314
|
+
if (intersectingHandles.length > 0) {
|
|
315
|
+
event.preventDefault();
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
function handlePointerUp(event) {
|
|
319
|
+
const {
|
|
320
|
+
x,
|
|
321
|
+
y
|
|
322
|
+
} = getResizeEventCoordinates(event);
|
|
323
|
+
panelConstraintFlags.clear();
|
|
324
|
+
isPointerDown = false;
|
|
325
|
+
if (intersectingHandles.length > 0) {
|
|
326
|
+
event.preventDefault();
|
|
327
|
+
}
|
|
328
|
+
recalculateIntersectingHandles({
|
|
329
|
+
x,
|
|
330
|
+
y
|
|
331
|
+
});
|
|
332
|
+
updateResizeHandlerStates("up", event);
|
|
333
|
+
updateCursor();
|
|
334
|
+
updateListeners();
|
|
335
|
+
}
|
|
336
|
+
function recalculateIntersectingHandles({
|
|
337
|
+
x,
|
|
338
|
+
y
|
|
339
|
+
}) {
|
|
340
|
+
intersectingHandles.splice(0);
|
|
341
|
+
registeredResizeHandlers.forEach(data => {
|
|
342
|
+
const {
|
|
343
|
+
element,
|
|
344
|
+
hitAreaMargins
|
|
345
|
+
} = data;
|
|
346
|
+
const {
|
|
347
|
+
bottom,
|
|
348
|
+
left,
|
|
349
|
+
right,
|
|
350
|
+
top
|
|
351
|
+
} = element.getBoundingClientRect();
|
|
352
|
+
const margin = isCoarsePointer ? hitAreaMargins.coarse : hitAreaMargins.fine;
|
|
353
|
+
const intersects = x >= left - margin && x <= right + margin && y >= top - margin && y <= bottom + margin;
|
|
354
|
+
if (intersects) {
|
|
355
|
+
intersectingHandles.push(data);
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
function reportConstraintsViolation(resizeHandleId, flag) {
|
|
360
|
+
panelConstraintFlags.set(resizeHandleId, flag);
|
|
361
|
+
}
|
|
362
|
+
function updateCursor() {
|
|
363
|
+
let intersectsHorizontal = false;
|
|
364
|
+
let intersectsVertical = false;
|
|
365
|
+
intersectingHandles.forEach(data => {
|
|
366
|
+
const {
|
|
367
|
+
direction
|
|
368
|
+
} = data;
|
|
369
|
+
if (direction === "horizontal") {
|
|
370
|
+
intersectsHorizontal = true;
|
|
371
|
+
} else {
|
|
372
|
+
intersectsVertical = true;
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
let constraintFlags = 0;
|
|
376
|
+
panelConstraintFlags.forEach(flag => {
|
|
377
|
+
constraintFlags |= flag;
|
|
378
|
+
});
|
|
379
|
+
if (intersectsHorizontal && intersectsVertical) {
|
|
380
|
+
setGlobalCursorStyle("intersection", constraintFlags);
|
|
381
|
+
} else if (intersectsHorizontal) {
|
|
382
|
+
setGlobalCursorStyle("horizontal", constraintFlags);
|
|
383
|
+
} else if (intersectsVertical) {
|
|
384
|
+
setGlobalCursorStyle("vertical", constraintFlags);
|
|
385
|
+
} else {
|
|
386
|
+
resetGlobalCursorStyle();
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
function updateListeners() {
|
|
390
|
+
ownerDocumentCounts.forEach((_, ownerDocument) => {
|
|
391
|
+
const {
|
|
392
|
+
body
|
|
393
|
+
} = ownerDocument;
|
|
394
|
+
body.removeEventListener("contextmenu", handlePointerUp);
|
|
395
|
+
body.removeEventListener("mousedown", handlePointerDown);
|
|
396
|
+
body.removeEventListener("mouseleave", handlePointerMove);
|
|
397
|
+
body.removeEventListener("mousemove", handlePointerMove);
|
|
398
|
+
body.removeEventListener("touchmove", handlePointerMove);
|
|
399
|
+
body.removeEventListener("touchstart", handlePointerDown);
|
|
400
|
+
});
|
|
401
|
+
window.removeEventListener("mouseup", handlePointerUp);
|
|
402
|
+
window.removeEventListener("touchcancel", handlePointerUp);
|
|
403
|
+
window.removeEventListener("touchend", handlePointerUp);
|
|
404
|
+
if (registerResizeHandle.length > 0) {
|
|
405
|
+
if (isPointerDown) {
|
|
406
|
+
if (intersectingHandles.length > 0) {
|
|
407
|
+
ownerDocumentCounts.forEach((count, ownerDocument) => {
|
|
408
|
+
const {
|
|
409
|
+
body
|
|
410
|
+
} = ownerDocument;
|
|
411
|
+
if (count > 0) {
|
|
412
|
+
body.addEventListener("contextmenu", handlePointerUp);
|
|
413
|
+
body.addEventListener("mouseleave", handlePointerMove);
|
|
414
|
+
body.addEventListener("mousemove", handlePointerMove);
|
|
415
|
+
body.addEventListener("touchmove", handlePointerMove, {
|
|
416
|
+
passive: false
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
window.addEventListener("mouseup", handlePointerUp);
|
|
422
|
+
window.addEventListener("touchcancel", handlePointerUp);
|
|
423
|
+
window.addEventListener("touchend", handlePointerUp);
|
|
424
|
+
} else {
|
|
425
|
+
ownerDocumentCounts.forEach((count, ownerDocument) => {
|
|
426
|
+
const {
|
|
427
|
+
body
|
|
428
|
+
} = ownerDocument;
|
|
429
|
+
if (count > 0) {
|
|
430
|
+
body.addEventListener("mousedown", handlePointerDown);
|
|
431
|
+
body.addEventListener("mousemove", handlePointerMove);
|
|
432
|
+
body.addEventListener("touchmove", handlePointerMove, {
|
|
433
|
+
passive: false
|
|
434
|
+
});
|
|
435
|
+
body.addEventListener("touchstart", handlePointerDown);
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
function updateResizeHandlerStates(action, event) {
|
|
442
|
+
registeredResizeHandlers.forEach(data => {
|
|
443
|
+
const {
|
|
444
|
+
setResizeHandlerState
|
|
445
|
+
} = data;
|
|
446
|
+
if (intersectingHandles.includes(data)) {
|
|
447
|
+
if (isPointerDown) {
|
|
448
|
+
setResizeHandlerState(action, "drag", event);
|
|
449
|
+
} else {
|
|
450
|
+
setResizeHandlerState(action, "hover", event);
|
|
451
|
+
}
|
|
452
|
+
} else {
|
|
453
|
+
setResizeHandlerState(action, "inactive", event);
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
|
|
142
458
|
function assert(expectedCondition, message = "Assertion failed!") {
|
|
143
459
|
if (!expectedCondition) {
|
|
144
460
|
console.error(message);
|
|
@@ -571,27 +887,13 @@ function areEqual(arrayA, arrayB) {
|
|
|
571
887
|
return true;
|
|
572
888
|
}
|
|
573
889
|
|
|
574
|
-
function isKeyDown(event) {
|
|
575
|
-
return event.type === "keydown";
|
|
576
|
-
}
|
|
577
|
-
function isMouseEvent(event) {
|
|
578
|
-
return event.type.startsWith("mouse");
|
|
579
|
-
}
|
|
580
|
-
function isTouchEvent(event) {
|
|
581
|
-
return event.type.startsWith("touch");
|
|
582
|
-
}
|
|
583
|
-
|
|
584
890
|
function getResizeEventCursorPosition(direction, event) {
|
|
585
891
|
const isHorizontal = direction === "horizontal";
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
return isHorizontal ? firstTouch.screenX : firstTouch.screenY;
|
|
592
|
-
} else {
|
|
593
|
-
throw Error(`Unsupported event type "${event.type}"`);
|
|
594
|
-
}
|
|
892
|
+
const {
|
|
893
|
+
x,
|
|
894
|
+
y
|
|
895
|
+
} = getResizeEventCoordinates(event);
|
|
896
|
+
return isHorizontal ? x : y;
|
|
595
897
|
}
|
|
596
898
|
|
|
597
899
|
function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState, panelGroupElement) {
|
|
@@ -740,44 +1042,6 @@ function computePanelFlexBoxStyle({
|
|
|
740
1042
|
};
|
|
741
1043
|
}
|
|
742
1044
|
|
|
743
|
-
let currentState = null;
|
|
744
|
-
let element = null;
|
|
745
|
-
function getCursorStyle(state) {
|
|
746
|
-
switch (state) {
|
|
747
|
-
case "horizontal":
|
|
748
|
-
return "ew-resize";
|
|
749
|
-
case "horizontal-max":
|
|
750
|
-
return "w-resize";
|
|
751
|
-
case "horizontal-min":
|
|
752
|
-
return "e-resize";
|
|
753
|
-
case "vertical":
|
|
754
|
-
return "ns-resize";
|
|
755
|
-
case "vertical-max":
|
|
756
|
-
return "n-resize";
|
|
757
|
-
case "vertical-min":
|
|
758
|
-
return "s-resize";
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
function resetGlobalCursorStyle() {
|
|
762
|
-
if (element !== null) {
|
|
763
|
-
document.head.removeChild(element);
|
|
764
|
-
currentState = null;
|
|
765
|
-
element = null;
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
function setGlobalCursorStyle(state) {
|
|
769
|
-
if (currentState === state) {
|
|
770
|
-
return;
|
|
771
|
-
}
|
|
772
|
-
currentState = state;
|
|
773
|
-
const style = getCursorStyle(state);
|
|
774
|
-
if (element === null) {
|
|
775
|
-
element = document.createElement("style");
|
|
776
|
-
document.head.appendChild(element);
|
|
777
|
-
}
|
|
778
|
-
element.innerHTML = `*{cursor: ${style}!important;}`;
|
|
779
|
-
}
|
|
780
|
-
|
|
781
1045
|
function debounce(callback, durationMs = 10) {
|
|
782
1046
|
let timeoutId = null;
|
|
783
1047
|
let callable = (...args) => {
|
|
@@ -1261,18 +1525,15 @@ function PanelGroupWithForwardedRef({
|
|
|
1261
1525
|
if (prevDeltaRef.current != delta) {
|
|
1262
1526
|
prevDeltaRef.current = delta;
|
|
1263
1527
|
if (!layoutChanged) {
|
|
1264
|
-
// If the pointer has moved too far to resize the panel any further,
|
|
1265
|
-
// update the cursor style for a visual clue.
|
|
1528
|
+
// If the pointer has moved too far to resize the panel any further, note this so we can update the cursor.
|
|
1266
1529
|
// This mimics VS Code behavior.
|
|
1267
|
-
|
|
1268
1530
|
if (isHorizontal) {
|
|
1269
|
-
|
|
1531
|
+
reportConstraintsViolation(dragHandleId, delta < 0 ? EXCEEDED_HORIZONTAL_MIN : EXCEEDED_HORIZONTAL_MAX);
|
|
1270
1532
|
} else {
|
|
1271
|
-
|
|
1533
|
+
reportConstraintsViolation(dragHandleId, delta < 0 ? EXCEEDED_VERTICAL_MIN : EXCEEDED_VERTICAL_MAX);
|
|
1272
1534
|
}
|
|
1273
1535
|
} else {
|
|
1274
|
-
|
|
1275
|
-
setGlobalCursorStyle(isHorizontal ? "horizontal" : "vertical");
|
|
1536
|
+
reportConstraintsViolation(dragHandleId, 0);
|
|
1276
1537
|
}
|
|
1277
1538
|
}
|
|
1278
1539
|
}
|
|
@@ -1327,15 +1588,11 @@ function PanelGroupWithForwardedRef({
|
|
|
1327
1588
|
} = eagerValuesRef.current;
|
|
1328
1589
|
const {
|
|
1329
1590
|
collapsedSize: prevCollapsedSize = 0,
|
|
1330
|
-
collapsible: prevCollapsible
|
|
1331
|
-
defaultSize: prevDefaultSize,
|
|
1332
|
-
maxSize: prevMaxSize = 100,
|
|
1333
|
-
minSize: prevMinSize = 0
|
|
1591
|
+
collapsible: prevCollapsible
|
|
1334
1592
|
} = prevConstraints;
|
|
1335
1593
|
const {
|
|
1336
1594
|
collapsedSize: nextCollapsedSize = 0,
|
|
1337
1595
|
collapsible: nextCollapsible,
|
|
1338
|
-
defaultSize: nextDefaultSize,
|
|
1339
1596
|
maxSize: nextMaxSize = 100,
|
|
1340
1597
|
minSize: nextMinSize = 0
|
|
1341
1598
|
} = panelData.constraints;
|
|
@@ -1343,8 +1600,10 @@ function PanelGroupWithForwardedRef({
|
|
|
1343
1600
|
panelSize: prevPanelSize
|
|
1344
1601
|
} = panelDataHelper(panelDataArray, panelData, layout);
|
|
1345
1602
|
assert(prevPanelSize != null);
|
|
1346
|
-
if (prevCollapsible && nextCollapsible &&
|
|
1347
|
-
|
|
1603
|
+
if (prevCollapsible && nextCollapsible && prevPanelSize === prevCollapsedSize) {
|
|
1604
|
+
if (prevCollapsedSize !== nextCollapsedSize) {
|
|
1605
|
+
resizePanel(panelData, nextCollapsedSize);
|
|
1606
|
+
}
|
|
1348
1607
|
} else if (prevPanelSize < nextMinSize) {
|
|
1349
1608
|
resizePanel(panelData, nextMinSize);
|
|
1350
1609
|
} else if (prevPanelSize > nextMaxSize) {
|
|
@@ -1372,7 +1631,6 @@ function PanelGroupWithForwardedRef({
|
|
|
1372
1631
|
});
|
|
1373
1632
|
}, []);
|
|
1374
1633
|
const stopDragging = useCallback(() => {
|
|
1375
|
-
resetGlobalCursorStyle();
|
|
1376
1634
|
setDragState(null);
|
|
1377
1635
|
}, []);
|
|
1378
1636
|
const unregisterPanel = useCallback(panelData => {
|
|
@@ -1513,6 +1771,7 @@ function PanelResizeHandle({
|
|
|
1513
1771
|
children = null,
|
|
1514
1772
|
className: classNameFromProps = "",
|
|
1515
1773
|
disabled = false,
|
|
1774
|
+
hitAreaMargins,
|
|
1516
1775
|
id: idFromProps,
|
|
1517
1776
|
onDragging,
|
|
1518
1777
|
style: styleFromProps = {},
|
|
@@ -1535,67 +1794,60 @@ function PanelResizeHandle({
|
|
|
1535
1794
|
}
|
|
1536
1795
|
const {
|
|
1537
1796
|
direction,
|
|
1538
|
-
dragState,
|
|
1539
1797
|
groupId,
|
|
1540
|
-
registerResizeHandle,
|
|
1798
|
+
registerResizeHandle: registerResizeHandleWithParentGroup,
|
|
1541
1799
|
startDragging,
|
|
1542
1800
|
stopDragging,
|
|
1543
1801
|
panelGroupElement
|
|
1544
1802
|
} = panelGroupContext;
|
|
1545
1803
|
const resizeHandleId = useUniqueId(idFromProps);
|
|
1546
|
-
const
|
|
1804
|
+
const [state, setState] = useState("inactive");
|
|
1547
1805
|
const [isFocused, setIsFocused] = useState(false);
|
|
1548
1806
|
const [resizeHandler, setResizeHandler] = useState(null);
|
|
1549
|
-
const stopDraggingAndBlur = useCallback(() => {
|
|
1550
|
-
// Clicking on the drag handle shouldn't leave it focused;
|
|
1551
|
-
// That would cause the PanelGroup to think it was still active.
|
|
1552
|
-
const element = elementRef.current;
|
|
1553
|
-
assert(element);
|
|
1554
|
-
element.blur();
|
|
1555
|
-
stopDragging();
|
|
1556
|
-
const {
|
|
1557
|
-
onDragging
|
|
1558
|
-
} = callbacksRef.current;
|
|
1559
|
-
if (onDragging) {
|
|
1560
|
-
onDragging(false);
|
|
1561
|
-
}
|
|
1562
|
-
}, [stopDragging]);
|
|
1563
1807
|
useEffect(() => {
|
|
1564
1808
|
if (disabled) {
|
|
1565
1809
|
setResizeHandler(null);
|
|
1566
1810
|
} else {
|
|
1567
|
-
const resizeHandler =
|
|
1811
|
+
const resizeHandler = registerResizeHandleWithParentGroup(resizeHandleId);
|
|
1568
1812
|
setResizeHandler(() => resizeHandler);
|
|
1569
1813
|
}
|
|
1570
|
-
}, [disabled, resizeHandleId,
|
|
1814
|
+
}, [disabled, resizeHandleId, registerResizeHandleWithParentGroup]);
|
|
1571
1815
|
useEffect(() => {
|
|
1572
|
-
|
|
1816
|
+
var _hitAreaMargins$coars, _hitAreaMargins$fine;
|
|
1817
|
+
if (disabled || resizeHandler == null) {
|
|
1573
1818
|
return;
|
|
1574
1819
|
}
|
|
1575
|
-
const onMove = event => {
|
|
1576
|
-
resizeHandler(event);
|
|
1577
|
-
};
|
|
1578
|
-
const onMouseLeave = event => {
|
|
1579
|
-
resizeHandler(event);
|
|
1580
|
-
};
|
|
1581
1820
|
const element = elementRef.current;
|
|
1582
1821
|
assert(element);
|
|
1583
|
-
const
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1822
|
+
const setResizeHandlerState = (action, state, event) => {
|
|
1823
|
+
setState(state);
|
|
1824
|
+
switch (action) {
|
|
1825
|
+
case "down":
|
|
1826
|
+
{
|
|
1827
|
+
startDragging(resizeHandleId, event);
|
|
1828
|
+
break;
|
|
1829
|
+
}
|
|
1830
|
+
case "up":
|
|
1831
|
+
{
|
|
1832
|
+
stopDragging();
|
|
1833
|
+
break;
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
switch (state) {
|
|
1837
|
+
case "drag":
|
|
1838
|
+
{
|
|
1839
|
+
resizeHandler(event);
|
|
1840
|
+
break;
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1597
1843
|
};
|
|
1598
|
-
|
|
1844
|
+
return registerResizeHandle(resizeHandleId, element, direction, {
|
|
1845
|
+
// Coarse inputs (e.g. finger/touch)
|
|
1846
|
+
coarse: (_hitAreaMargins$coars = hitAreaMargins === null || hitAreaMargins === void 0 ? void 0 : hitAreaMargins.coarse) !== null && _hitAreaMargins$coars !== void 0 ? _hitAreaMargins$coars : 15,
|
|
1847
|
+
// Fine inputs (e.g. mouse)
|
|
1848
|
+
fine: (_hitAreaMargins$fine = hitAreaMargins === null || hitAreaMargins === void 0 ? void 0 : hitAreaMargins.fine) !== null && _hitAreaMargins$fine !== void 0 ? _hitAreaMargins$fine : 5
|
|
1849
|
+
}, setResizeHandlerState);
|
|
1850
|
+
}, [direction, disabled, hitAreaMargins, registerResizeHandleWithParentGroup, resizeHandleId, resizeHandler, startDragging, stopDragging]);
|
|
1599
1851
|
useWindowSplitterResizeHandlerBehavior({
|
|
1600
1852
|
disabled,
|
|
1601
1853
|
handleId: resizeHandleId,
|
|
@@ -1603,7 +1855,6 @@ function PanelResizeHandle({
|
|
|
1603
1855
|
panelGroupElement
|
|
1604
1856
|
});
|
|
1605
1857
|
const style = {
|
|
1606
|
-
cursor: getCursorStyle(direction),
|
|
1607
1858
|
touchAction: "none",
|
|
1608
1859
|
userSelect: "none"
|
|
1609
1860
|
};
|
|
@@ -1613,31 +1864,6 @@ function PanelResizeHandle({
|
|
|
1613
1864
|
className: classNameFromProps,
|
|
1614
1865
|
onBlur: () => setIsFocused(false),
|
|
1615
1866
|
onFocus: () => setIsFocused(true),
|
|
1616
|
-
onMouseDown: event => {
|
|
1617
|
-
startDragging(resizeHandleId, event.nativeEvent);
|
|
1618
|
-
const callbacks = callbacksRef.current;
|
|
1619
|
-
assert(callbacks);
|
|
1620
|
-
const {
|
|
1621
|
-
onDragging
|
|
1622
|
-
} = callbacks;
|
|
1623
|
-
if (onDragging) {
|
|
1624
|
-
onDragging(true);
|
|
1625
|
-
}
|
|
1626
|
-
},
|
|
1627
|
-
onMouseUp: stopDraggingAndBlur,
|
|
1628
|
-
onTouchCancel: stopDraggingAndBlur,
|
|
1629
|
-
onTouchEnd: stopDraggingAndBlur,
|
|
1630
|
-
onTouchStart: event => {
|
|
1631
|
-
startDragging(resizeHandleId, event.nativeEvent);
|
|
1632
|
-
const callbacks = callbacksRef.current;
|
|
1633
|
-
assert(callbacks);
|
|
1634
|
-
const {
|
|
1635
|
-
onDragging
|
|
1636
|
-
} = callbacks;
|
|
1637
|
-
if (onDragging) {
|
|
1638
|
-
onDragging(true);
|
|
1639
|
-
}
|
|
1640
|
-
},
|
|
1641
1867
|
ref: elementRef,
|
|
1642
1868
|
role: "separator",
|
|
1643
1869
|
style: {
|
|
@@ -1649,7 +1875,8 @@ function PanelResizeHandle({
|
|
|
1649
1875
|
"data-panel-group-direction": direction,
|
|
1650
1876
|
"data-panel-group-id": groupId,
|
|
1651
1877
|
"data-resize-handle": "",
|
|
1652
|
-
"data-resize-handle-active":
|
|
1878
|
+
"data-resize-handle-active": state === "drag" ? "pointer" : isFocused ? "keyboard" : undefined,
|
|
1879
|
+
"data-resize-handle-state": state,
|
|
1653
1880
|
"data-panel-resize-handle-enabled": !disabled,
|
|
1654
1881
|
"data-panel-resize-handle-id": resizeHandleId
|
|
1655
1882
|
});
|
package/package.json
CHANGED
package/src/Panel.test.tsx
CHANGED
|
@@ -319,6 +319,58 @@ describe("PanelGroup", () => {
|
|
|
319
319
|
expect(rightElement.getAttribute("data-panel-size")).toBe("5.0");
|
|
320
320
|
});
|
|
321
321
|
|
|
322
|
+
it("it should not expand a collapsed panel if other constraints change", () => {
|
|
323
|
+
act(() => {
|
|
324
|
+
root.render(
|
|
325
|
+
<PanelGroup direction="horizontal">
|
|
326
|
+
<Panel
|
|
327
|
+
id="left"
|
|
328
|
+
collapsedSize={10}
|
|
329
|
+
collapsible
|
|
330
|
+
defaultSize={10}
|
|
331
|
+
minSize={25}
|
|
332
|
+
/>
|
|
333
|
+
<PanelResizeHandle />
|
|
334
|
+
<Panel id="middle" />
|
|
335
|
+
<PanelResizeHandle />
|
|
336
|
+
<Panel
|
|
337
|
+
id="right"
|
|
338
|
+
collapsedSize={10}
|
|
339
|
+
collapsible
|
|
340
|
+
defaultSize={10}
|
|
341
|
+
minSize={25}
|
|
342
|
+
/>
|
|
343
|
+
</PanelGroup>
|
|
344
|
+
);
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
let leftElement = getPanelElement("left", container);
|
|
348
|
+
let middleElement = getPanelElement("middle", container);
|
|
349
|
+
let rightElement = getPanelElement("right", container);
|
|
350
|
+
assert(leftElement);
|
|
351
|
+
assert(middleElement);
|
|
352
|
+
assert(rightElement);
|
|
353
|
+
expect(leftElement.getAttribute("data-panel-size")).toBe("10.0");
|
|
354
|
+
expect(middleElement.getAttribute("data-panel-size")).toBe("80.0");
|
|
355
|
+
expect(rightElement.getAttribute("data-panel-size")).toBe("10.0");
|
|
356
|
+
|
|
357
|
+
act(() => {
|
|
358
|
+
root.render(
|
|
359
|
+
<PanelGroup direction="horizontal">
|
|
360
|
+
<Panel id="left" collapsedSize={10} collapsible minSize={20} />
|
|
361
|
+
<PanelResizeHandle />
|
|
362
|
+
<Panel id="middle" />
|
|
363
|
+
<PanelResizeHandle />
|
|
364
|
+
<Panel id="right" collapsedSize={10} collapsible minSize={20} />
|
|
365
|
+
</PanelGroup>
|
|
366
|
+
);
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
expect(leftElement.getAttribute("data-panel-size")).toBe("10.0");
|
|
370
|
+
expect(middleElement.getAttribute("data-panel-size")).toBe("80.0");
|
|
371
|
+
expect(rightElement.getAttribute("data-panel-size")).toBe("10.0");
|
|
372
|
+
});
|
|
373
|
+
|
|
322
374
|
it("should resize a panel if the minSize prop changes", () => {
|
|
323
375
|
act(() => {
|
|
324
376
|
root.render(
|