react-resizable-panels 2.0.19 → 2.0.20
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 +5 -0
- package/README.md +3 -0
- package/dist/declarations/src/PanelResizeHandle.d.ts +5 -3
- package/dist/declarations/src/index.d.ts +2 -1
- package/dist/react-resizable-panels.browser.cjs.js +20 -2
- package/dist/react-resizable-panels.browser.development.cjs.js +20 -2
- package/dist/react-resizable-panels.browser.development.esm.js +20 -2
- package/dist/react-resizable-panels.browser.esm.js +20 -2
- package/dist/react-resizable-panels.cjs.js +20 -2
- package/dist/react-resizable-panels.development.cjs.js +20 -2
- package/dist/react-resizable-panels.development.esm.js +20 -2
- package/dist/react-resizable-panels.development.node.cjs.js +20 -2
- package/dist/react-resizable-panels.development.node.esm.js +20 -2
- package/dist/react-resizable-panels.esm.js +20 -2
- package/dist/react-resizable-panels.node.cjs.js +20 -2
- package/dist/react-resizable-panels.node.esm.js +20 -2
- package/package.json +1 -1
- package/src/PanelResizeHandle.test.tsx +42 -2
- package/src/PanelResizeHandle.ts +25 -16
- package/src/PanelResizeHandleRegistry.ts +11 -0
- package/src/index.ts +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.0.20
|
|
4
|
+
|
|
5
|
+
- Reset global cursor if an active resize handle is unmounted (#313)
|
|
6
|
+
- Resize handle supports (optional) `onFocus` or `onBlur` props (#370)
|
|
7
|
+
|
|
3
8
|
## 2.0.19
|
|
4
9
|
|
|
5
10
|
- Add optional `minSize` override param to panel `expand` imperative API
|
package/README.md
CHANGED
|
@@ -223,4 +223,7 @@ export function ClientComponent({
|
|
|
223
223
|
}
|
|
224
224
|
```
|
|
225
225
|
|
|
226
|
+
> [!NOTE]
|
|
227
|
+
> Be sure to specify a `defaultSize` prop for **every** `Panel` component to avoid layout flicker.
|
|
228
|
+
|
|
226
229
|
A demo of this is available [here](https://github.com/bvaughn/react-resizable-panels-demo-ssr).
|
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
import { CSSProperties, HTMLAttributes, PropsWithChildren, ReactElement } from "./vendor/react.js";
|
|
2
1
|
import { PointerHitAreaMargins } from "./PanelResizeHandleRegistry.js";
|
|
2
|
+
import { CSSProperties, HTMLAttributes, PropsWithChildren, ReactElement } from "./vendor/react.js";
|
|
3
3
|
export type PanelResizeHandleOnDragging = (isDragging: boolean) => void;
|
|
4
4
|
export type ResizeHandlerState = "drag" | "hover" | "inactive";
|
|
5
|
-
export type PanelResizeHandleProps = Omit<HTMLAttributes<keyof HTMLElementTagNameMap>, "id"> & PropsWithChildren<{
|
|
5
|
+
export type PanelResizeHandleProps = Omit<HTMLAttributes<keyof HTMLElementTagNameMap>, "id" | "onBlur" | "onFocus"> & PropsWithChildren<{
|
|
6
6
|
className?: string;
|
|
7
7
|
disabled?: boolean;
|
|
8
8
|
hitAreaMargins?: PointerHitAreaMargins;
|
|
9
9
|
id?: string | null;
|
|
10
|
+
onBlur?: () => void;
|
|
10
11
|
onDragging?: PanelResizeHandleOnDragging;
|
|
12
|
+
onFocus?: () => void;
|
|
11
13
|
style?: CSSProperties;
|
|
12
14
|
tabIndex?: number;
|
|
13
15
|
tagName?: keyof HTMLElementTagNameMap;
|
|
14
16
|
}>;
|
|
15
|
-
export declare function PanelResizeHandle({ children, className: classNameFromProps, disabled, hitAreaMargins, id: idFromProps, onDragging, style: styleFromProps, tabIndex, tagName: Type, ...rest }: PanelResizeHandleProps): ReactElement;
|
|
17
|
+
export declare function PanelResizeHandle({ children, className: classNameFromProps, disabled, hitAreaMargins, id: idFromProps, onBlur, onDragging, onFocus, style: styleFromProps, tabIndex, tagName: Type, ...rest }: PanelResizeHandleProps): ReactElement;
|
|
16
18
|
export declare namespace PanelResizeHandle {
|
|
17
19
|
var displayName: string;
|
|
18
20
|
}
|
|
@@ -14,4 +14,5 @@ import { intersects } from "./utils/rects/intersects.js";
|
|
|
14
14
|
import type { ImperativePanelHandle, PanelOnCollapse, PanelOnExpand, PanelOnResize, PanelProps } from "./Panel.js";
|
|
15
15
|
import type { ImperativePanelGroupHandle, PanelGroupOnLayout, PanelGroupProps, PanelGroupStorage } from "./PanelGroup.js";
|
|
16
16
|
import type { PanelResizeHandleOnDragging, PanelResizeHandleProps } from "./PanelResizeHandle.js";
|
|
17
|
-
|
|
17
|
+
import type { PointerHitAreaMargins } from "./PanelResizeHandleRegistry.js";
|
|
18
|
+
export { ImperativePanelGroupHandle, ImperativePanelHandle, PanelGroupOnLayout, PanelGroupProps, PanelGroupStorage, PanelOnCollapse, PanelOnExpand, PanelOnResize, PanelProps, PanelResizeHandleOnDragging, PanelResizeHandleProps, PointerHitAreaMargins, Panel, PanelGroup, PanelResizeHandle, assert, getIntersectingRectangle, intersects, getPanelElement, getPanelElementsForGroup, getPanelGroupElement, getResizeHandleElement, getResizeHandleElementIndex, getResizeHandleElementsForGroup, getResizeHandlePanelIds, };
|
|
@@ -454,6 +454,16 @@ function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins
|
|
|
454
454
|
if (count === 1) {
|
|
455
455
|
ownerDocumentCounts.delete(ownerDocument);
|
|
456
456
|
}
|
|
457
|
+
|
|
458
|
+
// If the resize handle that is currently unmounting is intersecting with the pointer,
|
|
459
|
+
// update the global pointer to account for the change
|
|
460
|
+
if (intersectingHandles.includes(data)) {
|
|
461
|
+
const index = intersectingHandles.indexOf(data);
|
|
462
|
+
if (index >= 0) {
|
|
463
|
+
intersectingHandles.splice(index, 1);
|
|
464
|
+
}
|
|
465
|
+
updateCursor();
|
|
466
|
+
}
|
|
457
467
|
};
|
|
458
468
|
}
|
|
459
469
|
function handlePointerDown(event) {
|
|
@@ -2203,7 +2213,9 @@ function PanelResizeHandle({
|
|
|
2203
2213
|
disabled = false,
|
|
2204
2214
|
hitAreaMargins,
|
|
2205
2215
|
id: idFromProps,
|
|
2216
|
+
onBlur,
|
|
2206
2217
|
onDragging,
|
|
2218
|
+
onFocus,
|
|
2207
2219
|
style: styleFromProps = {},
|
|
2208
2220
|
tabIndex = 0,
|
|
2209
2221
|
tagName: Type = "div",
|
|
@@ -2323,8 +2335,14 @@ function PanelResizeHandle({
|
|
|
2323
2335
|
children,
|
|
2324
2336
|
className: classNameFromProps,
|
|
2325
2337
|
id: idFromProps,
|
|
2326
|
-
onBlur: () =>
|
|
2327
|
-
|
|
2338
|
+
onBlur: () => {
|
|
2339
|
+
setIsFocused(false);
|
|
2340
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur();
|
|
2341
|
+
},
|
|
2342
|
+
onFocus: () => {
|
|
2343
|
+
setIsFocused(true);
|
|
2344
|
+
onFocus === null || onFocus === void 0 ? void 0 : onFocus();
|
|
2345
|
+
},
|
|
2328
2346
|
ref: elementRef,
|
|
2329
2347
|
role: "separator",
|
|
2330
2348
|
style: {
|
|
@@ -460,6 +460,16 @@ function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins
|
|
|
460
460
|
if (count === 1) {
|
|
461
461
|
ownerDocumentCounts.delete(ownerDocument);
|
|
462
462
|
}
|
|
463
|
+
|
|
464
|
+
// If the resize handle that is currently unmounting is intersecting with the pointer,
|
|
465
|
+
// update the global pointer to account for the change
|
|
466
|
+
if (intersectingHandles.includes(data)) {
|
|
467
|
+
const index = intersectingHandles.indexOf(data);
|
|
468
|
+
if (index >= 0) {
|
|
469
|
+
intersectingHandles.splice(index, 1);
|
|
470
|
+
}
|
|
471
|
+
updateCursor();
|
|
472
|
+
}
|
|
463
473
|
};
|
|
464
474
|
}
|
|
465
475
|
function handlePointerDown(event) {
|
|
@@ -2309,7 +2319,9 @@ function PanelResizeHandle({
|
|
|
2309
2319
|
disabled = false,
|
|
2310
2320
|
hitAreaMargins,
|
|
2311
2321
|
id: idFromProps,
|
|
2322
|
+
onBlur,
|
|
2312
2323
|
onDragging,
|
|
2324
|
+
onFocus,
|
|
2313
2325
|
style: styleFromProps = {},
|
|
2314
2326
|
tabIndex = 0,
|
|
2315
2327
|
tagName: Type = "div",
|
|
@@ -2429,8 +2441,14 @@ function PanelResizeHandle({
|
|
|
2429
2441
|
children,
|
|
2430
2442
|
className: classNameFromProps,
|
|
2431
2443
|
id: idFromProps,
|
|
2432
|
-
onBlur: () =>
|
|
2433
|
-
|
|
2444
|
+
onBlur: () => {
|
|
2445
|
+
setIsFocused(false);
|
|
2446
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur();
|
|
2447
|
+
},
|
|
2448
|
+
onFocus: () => {
|
|
2449
|
+
setIsFocused(true);
|
|
2450
|
+
onFocus === null || onFocus === void 0 ? void 0 : onFocus();
|
|
2451
|
+
},
|
|
2434
2452
|
ref: elementRef,
|
|
2435
2453
|
role: "separator",
|
|
2436
2454
|
style: {
|
|
@@ -436,6 +436,16 @@ function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins
|
|
|
436
436
|
if (count === 1) {
|
|
437
437
|
ownerDocumentCounts.delete(ownerDocument);
|
|
438
438
|
}
|
|
439
|
+
|
|
440
|
+
// If the resize handle that is currently unmounting is intersecting with the pointer,
|
|
441
|
+
// update the global pointer to account for the change
|
|
442
|
+
if (intersectingHandles.includes(data)) {
|
|
443
|
+
const index = intersectingHandles.indexOf(data);
|
|
444
|
+
if (index >= 0) {
|
|
445
|
+
intersectingHandles.splice(index, 1);
|
|
446
|
+
}
|
|
447
|
+
updateCursor();
|
|
448
|
+
}
|
|
439
449
|
};
|
|
440
450
|
}
|
|
441
451
|
function handlePointerDown(event) {
|
|
@@ -2285,7 +2295,9 @@ function PanelResizeHandle({
|
|
|
2285
2295
|
disabled = false,
|
|
2286
2296
|
hitAreaMargins,
|
|
2287
2297
|
id: idFromProps,
|
|
2298
|
+
onBlur,
|
|
2288
2299
|
onDragging,
|
|
2300
|
+
onFocus,
|
|
2289
2301
|
style: styleFromProps = {},
|
|
2290
2302
|
tabIndex = 0,
|
|
2291
2303
|
tagName: Type = "div",
|
|
@@ -2405,8 +2417,14 @@ function PanelResizeHandle({
|
|
|
2405
2417
|
children,
|
|
2406
2418
|
className: classNameFromProps,
|
|
2407
2419
|
id: idFromProps,
|
|
2408
|
-
onBlur: () =>
|
|
2409
|
-
|
|
2420
|
+
onBlur: () => {
|
|
2421
|
+
setIsFocused(false);
|
|
2422
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur();
|
|
2423
|
+
},
|
|
2424
|
+
onFocus: () => {
|
|
2425
|
+
setIsFocused(true);
|
|
2426
|
+
onFocus === null || onFocus === void 0 ? void 0 : onFocus();
|
|
2427
|
+
},
|
|
2410
2428
|
ref: elementRef,
|
|
2411
2429
|
role: "separator",
|
|
2412
2430
|
style: {
|
|
@@ -430,6 +430,16 @@ function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins
|
|
|
430
430
|
if (count === 1) {
|
|
431
431
|
ownerDocumentCounts.delete(ownerDocument);
|
|
432
432
|
}
|
|
433
|
+
|
|
434
|
+
// If the resize handle that is currently unmounting is intersecting with the pointer,
|
|
435
|
+
// update the global pointer to account for the change
|
|
436
|
+
if (intersectingHandles.includes(data)) {
|
|
437
|
+
const index = intersectingHandles.indexOf(data);
|
|
438
|
+
if (index >= 0) {
|
|
439
|
+
intersectingHandles.splice(index, 1);
|
|
440
|
+
}
|
|
441
|
+
updateCursor();
|
|
442
|
+
}
|
|
433
443
|
};
|
|
434
444
|
}
|
|
435
445
|
function handlePointerDown(event) {
|
|
@@ -2179,7 +2189,9 @@ function PanelResizeHandle({
|
|
|
2179
2189
|
disabled = false,
|
|
2180
2190
|
hitAreaMargins,
|
|
2181
2191
|
id: idFromProps,
|
|
2192
|
+
onBlur,
|
|
2182
2193
|
onDragging,
|
|
2194
|
+
onFocus,
|
|
2183
2195
|
style: styleFromProps = {},
|
|
2184
2196
|
tabIndex = 0,
|
|
2185
2197
|
tagName: Type = "div",
|
|
@@ -2299,8 +2311,14 @@ function PanelResizeHandle({
|
|
|
2299
2311
|
children,
|
|
2300
2312
|
className: classNameFromProps,
|
|
2301
2313
|
id: idFromProps,
|
|
2302
|
-
onBlur: () =>
|
|
2303
|
-
|
|
2314
|
+
onBlur: () => {
|
|
2315
|
+
setIsFocused(false);
|
|
2316
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur();
|
|
2317
|
+
},
|
|
2318
|
+
onFocus: () => {
|
|
2319
|
+
setIsFocused(true);
|
|
2320
|
+
onFocus === null || onFocus === void 0 ? void 0 : onFocus();
|
|
2321
|
+
},
|
|
2304
2322
|
ref: elementRef,
|
|
2305
2323
|
role: "separator",
|
|
2306
2324
|
style: {
|
|
@@ -456,6 +456,16 @@ function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins
|
|
|
456
456
|
if (count === 1) {
|
|
457
457
|
ownerDocumentCounts.delete(ownerDocument);
|
|
458
458
|
}
|
|
459
|
+
|
|
460
|
+
// If the resize handle that is currently unmounting is intersecting with the pointer,
|
|
461
|
+
// update the global pointer to account for the change
|
|
462
|
+
if (intersectingHandles.includes(data)) {
|
|
463
|
+
const index = intersectingHandles.indexOf(data);
|
|
464
|
+
if (index >= 0) {
|
|
465
|
+
intersectingHandles.splice(index, 1);
|
|
466
|
+
}
|
|
467
|
+
updateCursor();
|
|
468
|
+
}
|
|
459
469
|
};
|
|
460
470
|
}
|
|
461
471
|
function handlePointerDown(event) {
|
|
@@ -2205,7 +2215,9 @@ function PanelResizeHandle({
|
|
|
2205
2215
|
disabled = false,
|
|
2206
2216
|
hitAreaMargins,
|
|
2207
2217
|
id: idFromProps,
|
|
2218
|
+
onBlur,
|
|
2208
2219
|
onDragging,
|
|
2220
|
+
onFocus,
|
|
2209
2221
|
style: styleFromProps = {},
|
|
2210
2222
|
tabIndex = 0,
|
|
2211
2223
|
tagName: Type = "div",
|
|
@@ -2325,8 +2337,14 @@ function PanelResizeHandle({
|
|
|
2325
2337
|
children,
|
|
2326
2338
|
className: classNameFromProps,
|
|
2327
2339
|
id: idFromProps,
|
|
2328
|
-
onBlur: () =>
|
|
2329
|
-
|
|
2340
|
+
onBlur: () => {
|
|
2341
|
+
setIsFocused(false);
|
|
2342
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur();
|
|
2343
|
+
},
|
|
2344
|
+
onFocus: () => {
|
|
2345
|
+
setIsFocused(true);
|
|
2346
|
+
onFocus === null || onFocus === void 0 ? void 0 : onFocus();
|
|
2347
|
+
},
|
|
2330
2348
|
ref: elementRef,
|
|
2331
2349
|
role: "separator",
|
|
2332
2350
|
style: {
|
|
@@ -467,6 +467,16 @@ function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins
|
|
|
467
467
|
if (count === 1) {
|
|
468
468
|
ownerDocumentCounts.delete(ownerDocument);
|
|
469
469
|
}
|
|
470
|
+
|
|
471
|
+
// If the resize handle that is currently unmounting is intersecting with the pointer,
|
|
472
|
+
// update the global pointer to account for the change
|
|
473
|
+
if (intersectingHandles.includes(data)) {
|
|
474
|
+
const index = intersectingHandles.indexOf(data);
|
|
475
|
+
if (index >= 0) {
|
|
476
|
+
intersectingHandles.splice(index, 1);
|
|
477
|
+
}
|
|
478
|
+
updateCursor();
|
|
479
|
+
}
|
|
470
480
|
};
|
|
471
481
|
}
|
|
472
482
|
function handlePointerDown(event) {
|
|
@@ -2316,7 +2326,9 @@ function PanelResizeHandle({
|
|
|
2316
2326
|
disabled = false,
|
|
2317
2327
|
hitAreaMargins,
|
|
2318
2328
|
id: idFromProps,
|
|
2329
|
+
onBlur,
|
|
2319
2330
|
onDragging,
|
|
2331
|
+
onFocus,
|
|
2320
2332
|
style: styleFromProps = {},
|
|
2321
2333
|
tabIndex = 0,
|
|
2322
2334
|
tagName: Type = "div",
|
|
@@ -2436,8 +2448,14 @@ function PanelResizeHandle({
|
|
|
2436
2448
|
children,
|
|
2437
2449
|
className: classNameFromProps,
|
|
2438
2450
|
id: idFromProps,
|
|
2439
|
-
onBlur: () =>
|
|
2440
|
-
|
|
2451
|
+
onBlur: () => {
|
|
2452
|
+
setIsFocused(false);
|
|
2453
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur();
|
|
2454
|
+
},
|
|
2455
|
+
onFocus: () => {
|
|
2456
|
+
setIsFocused(true);
|
|
2457
|
+
onFocus === null || onFocus === void 0 ? void 0 : onFocus();
|
|
2458
|
+
},
|
|
2441
2459
|
ref: elementRef,
|
|
2442
2460
|
role: "separator",
|
|
2443
2461
|
style: {
|
|
@@ -443,6 +443,16 @@ function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins
|
|
|
443
443
|
if (count === 1) {
|
|
444
444
|
ownerDocumentCounts.delete(ownerDocument);
|
|
445
445
|
}
|
|
446
|
+
|
|
447
|
+
// If the resize handle that is currently unmounting is intersecting with the pointer,
|
|
448
|
+
// update the global pointer to account for the change
|
|
449
|
+
if (intersectingHandles.includes(data)) {
|
|
450
|
+
const index = intersectingHandles.indexOf(data);
|
|
451
|
+
if (index >= 0) {
|
|
452
|
+
intersectingHandles.splice(index, 1);
|
|
453
|
+
}
|
|
454
|
+
updateCursor();
|
|
455
|
+
}
|
|
446
456
|
};
|
|
447
457
|
}
|
|
448
458
|
function handlePointerDown(event) {
|
|
@@ -2292,7 +2302,9 @@ function PanelResizeHandle({
|
|
|
2292
2302
|
disabled = false,
|
|
2293
2303
|
hitAreaMargins,
|
|
2294
2304
|
id: idFromProps,
|
|
2305
|
+
onBlur,
|
|
2295
2306
|
onDragging,
|
|
2307
|
+
onFocus,
|
|
2296
2308
|
style: styleFromProps = {},
|
|
2297
2309
|
tabIndex = 0,
|
|
2298
2310
|
tagName: Type = "div",
|
|
@@ -2412,8 +2424,14 @@ function PanelResizeHandle({
|
|
|
2412
2424
|
children,
|
|
2413
2425
|
className: classNameFromProps,
|
|
2414
2426
|
id: idFromProps,
|
|
2415
|
-
onBlur: () =>
|
|
2416
|
-
|
|
2427
|
+
onBlur: () => {
|
|
2428
|
+
setIsFocused(false);
|
|
2429
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur();
|
|
2430
|
+
},
|
|
2431
|
+
onFocus: () => {
|
|
2432
|
+
setIsFocused(true);
|
|
2433
|
+
onFocus === null || onFocus === void 0 ? void 0 : onFocus();
|
|
2434
|
+
},
|
|
2417
2435
|
ref: elementRef,
|
|
2418
2436
|
role: "separator",
|
|
2419
2437
|
style: {
|
|
@@ -429,6 +429,16 @@ function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins
|
|
|
429
429
|
if (count === 1) {
|
|
430
430
|
ownerDocumentCounts.delete(ownerDocument);
|
|
431
431
|
}
|
|
432
|
+
|
|
433
|
+
// If the resize handle that is currently unmounting is intersecting with the pointer,
|
|
434
|
+
// update the global pointer to account for the change
|
|
435
|
+
if (intersectingHandles.includes(data)) {
|
|
436
|
+
const index = intersectingHandles.indexOf(data);
|
|
437
|
+
if (index >= 0) {
|
|
438
|
+
intersectingHandles.splice(index, 1);
|
|
439
|
+
}
|
|
440
|
+
updateCursor();
|
|
441
|
+
}
|
|
432
442
|
};
|
|
433
443
|
}
|
|
434
444
|
function handlePointerDown(event) {
|
|
@@ -2084,7 +2094,9 @@ function PanelResizeHandle({
|
|
|
2084
2094
|
disabled = false,
|
|
2085
2095
|
hitAreaMargins,
|
|
2086
2096
|
id: idFromProps,
|
|
2097
|
+
onBlur,
|
|
2087
2098
|
onDragging,
|
|
2099
|
+
onFocus,
|
|
2088
2100
|
style: styleFromProps = {},
|
|
2089
2101
|
tabIndex = 0,
|
|
2090
2102
|
tagName: Type = "div",
|
|
@@ -2201,8 +2213,14 @@ function PanelResizeHandle({
|
|
|
2201
2213
|
children,
|
|
2202
2214
|
className: classNameFromProps,
|
|
2203
2215
|
id: idFromProps,
|
|
2204
|
-
onBlur: () =>
|
|
2205
|
-
|
|
2216
|
+
onBlur: () => {
|
|
2217
|
+
setIsFocused(false);
|
|
2218
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur();
|
|
2219
|
+
},
|
|
2220
|
+
onFocus: () => {
|
|
2221
|
+
setIsFocused(true);
|
|
2222
|
+
onFocus === null || onFocus === void 0 ? void 0 : onFocus();
|
|
2223
|
+
},
|
|
2206
2224
|
ref: elementRef,
|
|
2207
2225
|
role: "separator",
|
|
2208
2226
|
style: {
|
|
@@ -405,6 +405,16 @@ function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins
|
|
|
405
405
|
if (count === 1) {
|
|
406
406
|
ownerDocumentCounts.delete(ownerDocument);
|
|
407
407
|
}
|
|
408
|
+
|
|
409
|
+
// If the resize handle that is currently unmounting is intersecting with the pointer,
|
|
410
|
+
// update the global pointer to account for the change
|
|
411
|
+
if (intersectingHandles.includes(data)) {
|
|
412
|
+
const index = intersectingHandles.indexOf(data);
|
|
413
|
+
if (index >= 0) {
|
|
414
|
+
intersectingHandles.splice(index, 1);
|
|
415
|
+
}
|
|
416
|
+
updateCursor();
|
|
417
|
+
}
|
|
408
418
|
};
|
|
409
419
|
}
|
|
410
420
|
function handlePointerDown(event) {
|
|
@@ -2060,7 +2070,9 @@ function PanelResizeHandle({
|
|
|
2060
2070
|
disabled = false,
|
|
2061
2071
|
hitAreaMargins,
|
|
2062
2072
|
id: idFromProps,
|
|
2073
|
+
onBlur,
|
|
2063
2074
|
onDragging,
|
|
2075
|
+
onFocus,
|
|
2064
2076
|
style: styleFromProps = {},
|
|
2065
2077
|
tabIndex = 0,
|
|
2066
2078
|
tagName: Type = "div",
|
|
@@ -2177,8 +2189,14 @@ function PanelResizeHandle({
|
|
|
2177
2189
|
children,
|
|
2178
2190
|
className: classNameFromProps,
|
|
2179
2191
|
id: idFromProps,
|
|
2180
|
-
onBlur: () =>
|
|
2181
|
-
|
|
2192
|
+
onBlur: () => {
|
|
2193
|
+
setIsFocused(false);
|
|
2194
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur();
|
|
2195
|
+
},
|
|
2196
|
+
onFocus: () => {
|
|
2197
|
+
setIsFocused(true);
|
|
2198
|
+
onFocus === null || onFocus === void 0 ? void 0 : onFocus();
|
|
2199
|
+
},
|
|
2182
2200
|
ref: elementRef,
|
|
2183
2201
|
role: "separator",
|
|
2184
2202
|
style: {
|
|
@@ -432,6 +432,16 @@ function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins
|
|
|
432
432
|
if (count === 1) {
|
|
433
433
|
ownerDocumentCounts.delete(ownerDocument);
|
|
434
434
|
}
|
|
435
|
+
|
|
436
|
+
// If the resize handle that is currently unmounting is intersecting with the pointer,
|
|
437
|
+
// update the global pointer to account for the change
|
|
438
|
+
if (intersectingHandles.includes(data)) {
|
|
439
|
+
const index = intersectingHandles.indexOf(data);
|
|
440
|
+
if (index >= 0) {
|
|
441
|
+
intersectingHandles.splice(index, 1);
|
|
442
|
+
}
|
|
443
|
+
updateCursor();
|
|
444
|
+
}
|
|
435
445
|
};
|
|
436
446
|
}
|
|
437
447
|
function handlePointerDown(event) {
|
|
@@ -2181,7 +2191,9 @@ function PanelResizeHandle({
|
|
|
2181
2191
|
disabled = false,
|
|
2182
2192
|
hitAreaMargins,
|
|
2183
2193
|
id: idFromProps,
|
|
2194
|
+
onBlur,
|
|
2184
2195
|
onDragging,
|
|
2196
|
+
onFocus,
|
|
2185
2197
|
style: styleFromProps = {},
|
|
2186
2198
|
tabIndex = 0,
|
|
2187
2199
|
tagName: Type = "div",
|
|
@@ -2301,8 +2313,14 @@ function PanelResizeHandle({
|
|
|
2301
2313
|
children,
|
|
2302
2314
|
className: classNameFromProps,
|
|
2303
2315
|
id: idFromProps,
|
|
2304
|
-
onBlur: () =>
|
|
2305
|
-
|
|
2316
|
+
onBlur: () => {
|
|
2317
|
+
setIsFocused(false);
|
|
2318
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur();
|
|
2319
|
+
},
|
|
2320
|
+
onFocus: () => {
|
|
2321
|
+
setIsFocused(true);
|
|
2322
|
+
onFocus === null || onFocus === void 0 ? void 0 : onFocus();
|
|
2323
|
+
},
|
|
2306
2324
|
ref: elementRef,
|
|
2307
2325
|
role: "separator",
|
|
2308
2326
|
style: {
|
|
@@ -418,6 +418,16 @@ function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins
|
|
|
418
418
|
if (count === 1) {
|
|
419
419
|
ownerDocumentCounts.delete(ownerDocument);
|
|
420
420
|
}
|
|
421
|
+
|
|
422
|
+
// If the resize handle that is currently unmounting is intersecting with the pointer,
|
|
423
|
+
// update the global pointer to account for the change
|
|
424
|
+
if (intersectingHandles.includes(data)) {
|
|
425
|
+
const index = intersectingHandles.indexOf(data);
|
|
426
|
+
if (index >= 0) {
|
|
427
|
+
intersectingHandles.splice(index, 1);
|
|
428
|
+
}
|
|
429
|
+
updateCursor();
|
|
430
|
+
}
|
|
421
431
|
};
|
|
422
432
|
}
|
|
423
433
|
function handlePointerDown(event) {
|
|
@@ -1983,7 +1993,9 @@ function PanelResizeHandle({
|
|
|
1983
1993
|
disabled = false,
|
|
1984
1994
|
hitAreaMargins,
|
|
1985
1995
|
id: idFromProps,
|
|
1996
|
+
onBlur,
|
|
1986
1997
|
onDragging,
|
|
1998
|
+
onFocus,
|
|
1987
1999
|
style: styleFromProps = {},
|
|
1988
2000
|
tabIndex = 0,
|
|
1989
2001
|
tagName: Type = "div",
|
|
@@ -2100,8 +2112,14 @@ function PanelResizeHandle({
|
|
|
2100
2112
|
children,
|
|
2101
2113
|
className: classNameFromProps,
|
|
2102
2114
|
id: idFromProps,
|
|
2103
|
-
onBlur: () =>
|
|
2104
|
-
|
|
2115
|
+
onBlur: () => {
|
|
2116
|
+
setIsFocused(false);
|
|
2117
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur();
|
|
2118
|
+
},
|
|
2119
|
+
onFocus: () => {
|
|
2120
|
+
setIsFocused(true);
|
|
2121
|
+
onFocus === null || onFocus === void 0 ? void 0 : onFocus();
|
|
2122
|
+
},
|
|
2105
2123
|
ref: elementRef,
|
|
2106
2124
|
role: "separator",
|
|
2107
2125
|
style: {
|
|
@@ -394,6 +394,16 @@ function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins
|
|
|
394
394
|
if (count === 1) {
|
|
395
395
|
ownerDocumentCounts.delete(ownerDocument);
|
|
396
396
|
}
|
|
397
|
+
|
|
398
|
+
// If the resize handle that is currently unmounting is intersecting with the pointer,
|
|
399
|
+
// update the global pointer to account for the change
|
|
400
|
+
if (intersectingHandles.includes(data)) {
|
|
401
|
+
const index = intersectingHandles.indexOf(data);
|
|
402
|
+
if (index >= 0) {
|
|
403
|
+
intersectingHandles.splice(index, 1);
|
|
404
|
+
}
|
|
405
|
+
updateCursor();
|
|
406
|
+
}
|
|
397
407
|
};
|
|
398
408
|
}
|
|
399
409
|
function handlePointerDown(event) {
|
|
@@ -1959,7 +1969,9 @@ function PanelResizeHandle({
|
|
|
1959
1969
|
disabled = false,
|
|
1960
1970
|
hitAreaMargins,
|
|
1961
1971
|
id: idFromProps,
|
|
1972
|
+
onBlur,
|
|
1962
1973
|
onDragging,
|
|
1974
|
+
onFocus,
|
|
1963
1975
|
style: styleFromProps = {},
|
|
1964
1976
|
tabIndex = 0,
|
|
1965
1977
|
tagName: Type = "div",
|
|
@@ -2076,8 +2088,14 @@ function PanelResizeHandle({
|
|
|
2076
2088
|
children,
|
|
2077
2089
|
className: classNameFromProps,
|
|
2078
2090
|
id: idFromProps,
|
|
2079
|
-
onBlur: () =>
|
|
2080
|
-
|
|
2091
|
+
onBlur: () => {
|
|
2092
|
+
setIsFocused(false);
|
|
2093
|
+
onBlur === null || onBlur === void 0 ? void 0 : onBlur();
|
|
2094
|
+
},
|
|
2095
|
+
onFocus: () => {
|
|
2096
|
+
setIsFocused(true);
|
|
2097
|
+
onFocus === null || onFocus === void 0 ? void 0 : onFocus();
|
|
2098
|
+
},
|
|
2081
2099
|
ref: elementRef,
|
|
2082
2100
|
role: "separator",
|
|
2083
2101
|
style: {
|
package/package.json
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { Root, createRoot } from "react-dom/client";
|
|
2
2
|
import { act } from "react-dom/test-utils";
|
|
3
|
-
import
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
Panel,
|
|
5
|
+
PanelGroup,
|
|
6
|
+
PanelResizeHandle,
|
|
7
|
+
type PanelResizeHandleProps,
|
|
8
|
+
} from ".";
|
|
5
9
|
import { assert } from "./utils/assert";
|
|
10
|
+
import * as cursorUtils from "./utils/cursor";
|
|
6
11
|
import { getResizeHandleElement } from "./utils/dom/getResizeHandleElement";
|
|
7
12
|
import {
|
|
8
13
|
dispatchPointerEvent,
|
|
@@ -10,6 +15,12 @@ import {
|
|
|
10
15
|
verifyAttribute,
|
|
11
16
|
} from "./utils/test-utils";
|
|
12
17
|
|
|
18
|
+
jest.mock("./utils/cursor", () => ({
|
|
19
|
+
getCursorStyle: jest.fn(),
|
|
20
|
+
resetGlobalCursorStyle: jest.fn(),
|
|
21
|
+
setGlobalCursorStyle: jest.fn(),
|
|
22
|
+
}));
|
|
23
|
+
|
|
13
24
|
describe("PanelResizeHandle", () => {
|
|
14
25
|
let expectedWarnings: string[] = [];
|
|
15
26
|
let root: Root;
|
|
@@ -305,4 +316,33 @@ describe("PanelResizeHandle", () => {
|
|
|
305
316
|
expect(element?.getAttribute("id")).toBeNull();
|
|
306
317
|
});
|
|
307
318
|
});
|
|
319
|
+
|
|
320
|
+
it("resets the global cursor style on unmount", () => {
|
|
321
|
+
const onDraggingLeft = jest.fn();
|
|
322
|
+
|
|
323
|
+
const { leftElement } = setupMockedGroup({
|
|
324
|
+
leftProps: { onDragging: onDraggingLeft },
|
|
325
|
+
rightProps: {},
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
act(() => {
|
|
329
|
+
dispatchPointerEvent("pointermove", leftElement);
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
act(() => {
|
|
333
|
+
dispatchPointerEvent("pointerdown", leftElement);
|
|
334
|
+
});
|
|
335
|
+
expect(onDraggingLeft).toHaveBeenCalledTimes(1);
|
|
336
|
+
expect(onDraggingLeft).toHaveBeenCalledWith(true);
|
|
337
|
+
|
|
338
|
+
expect(cursorUtils.resetGlobalCursorStyle).not.toHaveBeenCalled();
|
|
339
|
+
expect(cursorUtils.setGlobalCursorStyle).toHaveBeenCalledTimes(1);
|
|
340
|
+
|
|
341
|
+
act(() => {
|
|
342
|
+
root.unmount();
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
expect(cursorUtils.resetGlobalCursorStyle).toHaveBeenCalled();
|
|
346
|
+
expect(cursorUtils.setGlobalCursorStyle).toHaveBeenCalledTimes(1);
|
|
347
|
+
});
|
|
308
348
|
});
|
package/src/PanelResizeHandle.ts
CHANGED
|
@@ -1,16 +1,5 @@
|
|
|
1
|
+
import useIsomorphicLayoutEffect from "./hooks/useIsomorphicEffect";
|
|
1
2
|
import useUniqueId from "./hooks/useUniqueId";
|
|
2
|
-
import {
|
|
3
|
-
createElement,
|
|
4
|
-
CSSProperties,
|
|
5
|
-
HTMLAttributes,
|
|
6
|
-
PropsWithChildren,
|
|
7
|
-
ReactElement,
|
|
8
|
-
useContext,
|
|
9
|
-
useEffect,
|
|
10
|
-
useRef,
|
|
11
|
-
useState,
|
|
12
|
-
} from "./vendor/react";
|
|
13
|
-
|
|
14
3
|
import { useWindowSplitterResizeHandlerBehavior } from "./hooks/useWindowSplitterBehavior";
|
|
15
4
|
import {
|
|
16
5
|
PanelGroupContext,
|
|
@@ -23,21 +12,33 @@ import {
|
|
|
23
12
|
ResizeHandlerAction,
|
|
24
13
|
} from "./PanelResizeHandleRegistry";
|
|
25
14
|
import { assert } from "./utils/assert";
|
|
26
|
-
import
|
|
15
|
+
import {
|
|
16
|
+
createElement,
|
|
17
|
+
CSSProperties,
|
|
18
|
+
HTMLAttributes,
|
|
19
|
+
PropsWithChildren,
|
|
20
|
+
ReactElement,
|
|
21
|
+
useContext,
|
|
22
|
+
useEffect,
|
|
23
|
+
useRef,
|
|
24
|
+
useState,
|
|
25
|
+
} from "./vendor/react";
|
|
27
26
|
|
|
28
27
|
export type PanelResizeHandleOnDragging = (isDragging: boolean) => void;
|
|
29
28
|
export type ResizeHandlerState = "drag" | "hover" | "inactive";
|
|
30
29
|
|
|
31
30
|
export type PanelResizeHandleProps = Omit<
|
|
32
31
|
HTMLAttributes<keyof HTMLElementTagNameMap>,
|
|
33
|
-
"id"
|
|
32
|
+
"id" | "onBlur" | "onFocus"
|
|
34
33
|
> &
|
|
35
34
|
PropsWithChildren<{
|
|
36
35
|
className?: string;
|
|
37
36
|
disabled?: boolean;
|
|
38
37
|
hitAreaMargins?: PointerHitAreaMargins;
|
|
39
38
|
id?: string | null;
|
|
39
|
+
onBlur?: () => void;
|
|
40
40
|
onDragging?: PanelResizeHandleOnDragging;
|
|
41
|
+
onFocus?: () => void;
|
|
41
42
|
style?: CSSProperties;
|
|
42
43
|
tabIndex?: number;
|
|
43
44
|
tagName?: keyof HTMLElementTagNameMap;
|
|
@@ -49,7 +50,9 @@ export function PanelResizeHandle({
|
|
|
49
50
|
disabled = false,
|
|
50
51
|
hitAreaMargins,
|
|
51
52
|
id: idFromProps,
|
|
53
|
+
onBlur,
|
|
52
54
|
onDragging,
|
|
55
|
+
onFocus,
|
|
53
56
|
style: styleFromProps = {},
|
|
54
57
|
tabIndex = 0,
|
|
55
58
|
tagName: Type = "div",
|
|
@@ -208,8 +211,14 @@ export function PanelResizeHandle({
|
|
|
208
211
|
children,
|
|
209
212
|
className: classNameFromProps,
|
|
210
213
|
id: idFromProps,
|
|
211
|
-
onBlur: () =>
|
|
212
|
-
|
|
214
|
+
onBlur: () => {
|
|
215
|
+
setIsFocused(false);
|
|
216
|
+
onBlur?.();
|
|
217
|
+
},
|
|
218
|
+
onFocus: () => {
|
|
219
|
+
setIsFocused(true);
|
|
220
|
+
onFocus?.();
|
|
221
|
+
},
|
|
213
222
|
ref: elementRef,
|
|
214
223
|
role: "separator",
|
|
215
224
|
style: {
|
|
@@ -73,6 +73,17 @@ export function registerResizeHandle(
|
|
|
73
73
|
if (count === 1) {
|
|
74
74
|
ownerDocumentCounts.delete(ownerDocument);
|
|
75
75
|
}
|
|
76
|
+
|
|
77
|
+
// If the resize handle that is currently unmounting is intersecting with the pointer,
|
|
78
|
+
// update the global pointer to account for the change
|
|
79
|
+
if (intersectingHandles.includes(data)) {
|
|
80
|
+
const index = intersectingHandles.indexOf(data);
|
|
81
|
+
if (index >= 0) {
|
|
82
|
+
intersectingHandles.splice(index, 1);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
updateCursor();
|
|
86
|
+
}
|
|
76
87
|
};
|
|
77
88
|
}
|
|
78
89
|
|
package/src/index.ts
CHANGED
|
@@ -29,6 +29,7 @@ import type {
|
|
|
29
29
|
PanelResizeHandleOnDragging,
|
|
30
30
|
PanelResizeHandleProps,
|
|
31
31
|
} from "./PanelResizeHandle";
|
|
32
|
+
import type { PointerHitAreaMargins } from "./PanelResizeHandleRegistry";
|
|
32
33
|
|
|
33
34
|
export {
|
|
34
35
|
// TypeScript types
|
|
@@ -43,6 +44,7 @@ export {
|
|
|
43
44
|
PanelProps,
|
|
44
45
|
PanelResizeHandleOnDragging,
|
|
45
46
|
PanelResizeHandleProps,
|
|
47
|
+
PointerHitAreaMargins,
|
|
46
48
|
|
|
47
49
|
// React components
|
|
48
50
|
Panel,
|