react-resizable-panels 1.0.0-rc.2 → 1.0.0-rc.4
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/dist/react-resizable-panels.browser.cjs.js +58 -115
- package/dist/react-resizable-panels.browser.development.cjs.js +58 -115
- package/dist/react-resizable-panels.browser.development.esm.js +58 -115
- package/dist/react-resizable-panels.browser.esm.js +58 -115
- package/dist/react-resizable-panels.cjs.d.ts +1 -88
- package/dist/react-resizable-panels.cjs.d.ts.map +1 -1
- package/dist/react-resizable-panels.cjs.js +1671 -1491
- package/dist/react-resizable-panels.development.cjs.js +58 -115
- package/dist/react-resizable-panels.development.esm.js +58 -115
- package/dist/react-resizable-panels.development.node.cjs.js +19 -170
- package/dist/react-resizable-panels.development.node.esm.js +19 -170
- package/dist/react-resizable-panels.esm.js +1646 -1486
- package/dist/react-resizable-panels.node.cjs.js +19 -170
- package/dist/react-resizable-panels.node.esm.js +19 -170
- package/package.json +1 -1
- package/src/Panel.test.tsx +223 -0
- package/src/PanelGroup.test.tsx +60 -0
- package/src/PanelGroup.ts +53 -136
- package/src/PanelResizeHandle.test.tsx +6 -0
- package/dist/react-resizable-panels.cjs.js.map +0 -1
- package/dist/react-resizable-panels.esm.js.map +0 -1
package/src/Panel.test.tsx
CHANGED
|
@@ -253,6 +253,229 @@ describe("PanelGroup", () => {
|
|
|
253
253
|
expect(element.title).toBe("bar");
|
|
254
254
|
});
|
|
255
255
|
|
|
256
|
+
describe("callbacks", () => {
|
|
257
|
+
describe("onCollapse", () => {
|
|
258
|
+
it("should be called on mount if a panels initial size is 0", () => {
|
|
259
|
+
let onCollapseLeft = jest.fn();
|
|
260
|
+
let onCollapseRight = jest.fn();
|
|
261
|
+
|
|
262
|
+
act(() => {
|
|
263
|
+
root.render(
|
|
264
|
+
<PanelGroup direction="horizontal">
|
|
265
|
+
<Panel collapsible defaultSize={0} onCollapse={onCollapseLeft} />
|
|
266
|
+
<PanelResizeHandle />
|
|
267
|
+
<Panel collapsible onCollapse={onCollapseRight} />
|
|
268
|
+
</PanelGroup>
|
|
269
|
+
);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
expect(onCollapseLeft).toHaveBeenCalledTimes(1);
|
|
273
|
+
expect(onCollapseRight).not.toHaveBeenCalled();
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
it("should be called when a panel is collapsed", () => {
|
|
277
|
+
let onCollapse = jest.fn();
|
|
278
|
+
|
|
279
|
+
let panelRef = createRef<ImperativePanelHandle>();
|
|
280
|
+
|
|
281
|
+
act(() => {
|
|
282
|
+
root.render(
|
|
283
|
+
<PanelGroup direction="horizontal">
|
|
284
|
+
<Panel collapsible onCollapse={onCollapse} ref={panelRef} />
|
|
285
|
+
<PanelResizeHandle />
|
|
286
|
+
<Panel />
|
|
287
|
+
</PanelGroup>
|
|
288
|
+
);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
expect(onCollapse).not.toHaveBeenCalled();
|
|
292
|
+
|
|
293
|
+
act(() => {
|
|
294
|
+
panelRef.current?.collapse();
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
expect(onCollapse).toHaveBeenCalledTimes(1);
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
describe("onExpand", () => {
|
|
302
|
+
it("should be called on mount if a collapsible panels initial size is not 0", () => {
|
|
303
|
+
let onExpandLeft = jest.fn();
|
|
304
|
+
let onExpandRight = jest.fn();
|
|
305
|
+
|
|
306
|
+
act(() => {
|
|
307
|
+
root.render(
|
|
308
|
+
<PanelGroup direction="horizontal">
|
|
309
|
+
<Panel collapsible onExpand={onExpandLeft} />
|
|
310
|
+
<PanelResizeHandle />
|
|
311
|
+
<Panel onExpand={onExpandRight} />
|
|
312
|
+
</PanelGroup>
|
|
313
|
+
);
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
expect(onExpandLeft).toHaveBeenCalledTimes(1);
|
|
317
|
+
expect(onExpandRight).not.toHaveBeenCalled();
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
it("should be called when a collapsible panel is expanded", () => {
|
|
321
|
+
let onExpand = jest.fn();
|
|
322
|
+
|
|
323
|
+
let panelRef = createRef<ImperativePanelHandle>();
|
|
324
|
+
|
|
325
|
+
act(() => {
|
|
326
|
+
root.render(
|
|
327
|
+
<PanelGroup direction="horizontal">
|
|
328
|
+
<Panel
|
|
329
|
+
collapsible
|
|
330
|
+
defaultSize={0}
|
|
331
|
+
onExpand={onExpand}
|
|
332
|
+
ref={panelRef}
|
|
333
|
+
/>
|
|
334
|
+
<PanelResizeHandle />
|
|
335
|
+
<Panel />
|
|
336
|
+
</PanelGroup>
|
|
337
|
+
);
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
expect(onExpand).not.toHaveBeenCalled();
|
|
341
|
+
|
|
342
|
+
act(() => {
|
|
343
|
+
panelRef.current?.resize(25);
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
expect(onExpand).toHaveBeenCalledTimes(1);
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
describe("onResize", () => {
|
|
351
|
+
it("should be called on mount", () => {
|
|
352
|
+
let onResizeLeft = jest.fn();
|
|
353
|
+
let onResizeMiddle = jest.fn();
|
|
354
|
+
let onResizeRight = jest.fn();
|
|
355
|
+
|
|
356
|
+
act(() => {
|
|
357
|
+
root.render(
|
|
358
|
+
<PanelGroup direction="horizontal">
|
|
359
|
+
<Panel id="left" onResize={onResizeLeft} order={1} />
|
|
360
|
+
<PanelResizeHandle />
|
|
361
|
+
<Panel
|
|
362
|
+
defaultSize={50}
|
|
363
|
+
id="middle"
|
|
364
|
+
onResize={onResizeMiddle}
|
|
365
|
+
order={2}
|
|
366
|
+
/>
|
|
367
|
+
<PanelResizeHandle />
|
|
368
|
+
<Panel id="right" onResize={onResizeRight} order={3} />
|
|
369
|
+
</PanelGroup>
|
|
370
|
+
);
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
expect(onResizeLeft).toHaveBeenCalledTimes(1);
|
|
374
|
+
expect(onResizeLeft).toHaveBeenCalledWith(25, undefined);
|
|
375
|
+
expect(onResizeMiddle).toHaveBeenCalledTimes(1);
|
|
376
|
+
expect(onResizeMiddle).toHaveBeenCalledWith(50, undefined);
|
|
377
|
+
expect(onResizeRight).toHaveBeenCalledTimes(1);
|
|
378
|
+
expect(onResizeRight).toHaveBeenCalledWith(25, undefined);
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
it("should be called when a panel is added or removed from the group", () => {
|
|
382
|
+
let onResizeLeft = jest.fn();
|
|
383
|
+
let onResizeMiddle = jest.fn();
|
|
384
|
+
let onResizeRight = jest.fn();
|
|
385
|
+
|
|
386
|
+
act(() => {
|
|
387
|
+
root.render(
|
|
388
|
+
<PanelGroup direction="horizontal">
|
|
389
|
+
<Panel
|
|
390
|
+
id="middle"
|
|
391
|
+
key="middle"
|
|
392
|
+
onResize={onResizeMiddle}
|
|
393
|
+
order={2}
|
|
394
|
+
/>
|
|
395
|
+
</PanelGroup>
|
|
396
|
+
);
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
expect(onResizeLeft).not.toHaveBeenCalled();
|
|
400
|
+
expect(onResizeMiddle).toHaveBeenCalledWith(100, undefined);
|
|
401
|
+
expect(onResizeRight).not.toHaveBeenCalled();
|
|
402
|
+
|
|
403
|
+
onResizeLeft.mockReset();
|
|
404
|
+
onResizeMiddle.mockReset();
|
|
405
|
+
onResizeRight.mockReset();
|
|
406
|
+
|
|
407
|
+
act(() => {
|
|
408
|
+
root.render(
|
|
409
|
+
<PanelGroup direction="horizontal">
|
|
410
|
+
<Panel
|
|
411
|
+
id="left"
|
|
412
|
+
key="left"
|
|
413
|
+
maxSize={25}
|
|
414
|
+
minSize={25}
|
|
415
|
+
onResize={onResizeLeft}
|
|
416
|
+
order={1}
|
|
417
|
+
/>
|
|
418
|
+
<PanelResizeHandle />
|
|
419
|
+
<Panel
|
|
420
|
+
id="middle"
|
|
421
|
+
key="middle"
|
|
422
|
+
onResize={onResizeMiddle}
|
|
423
|
+
order={2}
|
|
424
|
+
/>
|
|
425
|
+
<PanelResizeHandle />
|
|
426
|
+
<Panel
|
|
427
|
+
id="right"
|
|
428
|
+
key="right"
|
|
429
|
+
maxSize={25}
|
|
430
|
+
minSize={25}
|
|
431
|
+
onResize={onResizeRight}
|
|
432
|
+
order={3}
|
|
433
|
+
/>
|
|
434
|
+
</PanelGroup>
|
|
435
|
+
);
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
expect(onResizeLeft).toHaveBeenCalledTimes(1);
|
|
439
|
+
expect(onResizeLeft).toHaveBeenCalledWith(25, undefined);
|
|
440
|
+
expect(onResizeMiddle).toHaveBeenCalledTimes(1);
|
|
441
|
+
expect(onResizeMiddle).toHaveBeenCalledWith(50, 100);
|
|
442
|
+
expect(onResizeRight).toHaveBeenCalledTimes(1);
|
|
443
|
+
expect(onResizeRight).toHaveBeenCalledWith(25, undefined);
|
|
444
|
+
|
|
445
|
+
onResizeLeft.mockReset();
|
|
446
|
+
onResizeMiddle.mockReset();
|
|
447
|
+
onResizeRight.mockReset();
|
|
448
|
+
|
|
449
|
+
act(() => {
|
|
450
|
+
root.render(
|
|
451
|
+
<PanelGroup direction="horizontal">
|
|
452
|
+
<Panel
|
|
453
|
+
id="left"
|
|
454
|
+
key="left"
|
|
455
|
+
maxSize={25}
|
|
456
|
+
minSize={25}
|
|
457
|
+
onResize={onResizeLeft}
|
|
458
|
+
order={1}
|
|
459
|
+
/>
|
|
460
|
+
<PanelResizeHandle />
|
|
461
|
+
<Panel
|
|
462
|
+
id="middle"
|
|
463
|
+
key="middle"
|
|
464
|
+
onResize={onResizeMiddle}
|
|
465
|
+
order={2}
|
|
466
|
+
/>
|
|
467
|
+
</PanelGroup>
|
|
468
|
+
);
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
expect(onResizeLeft).not.toHaveBeenCalled();
|
|
472
|
+
expect(onResizeMiddle).toHaveBeenCalledTimes(1);
|
|
473
|
+
expect(onResizeMiddle).toHaveBeenCalledWith(75, 50);
|
|
474
|
+
expect(onResizeRight).not.toHaveBeenCalled();
|
|
475
|
+
});
|
|
476
|
+
});
|
|
477
|
+
});
|
|
478
|
+
|
|
256
479
|
describe("DEV warnings", () => {
|
|
257
480
|
it("should warn about server rendered panels with no default size", () => {
|
|
258
481
|
jest.resetModules();
|
package/src/PanelGroup.test.tsx
CHANGED
|
@@ -2,6 +2,7 @@ import { Root, createRoot } from "react-dom/client";
|
|
|
2
2
|
import { act } from "react-dom/test-utils";
|
|
3
3
|
import {
|
|
4
4
|
ImperativePanelGroupHandle,
|
|
5
|
+
ImperativePanelHandle,
|
|
5
6
|
Panel,
|
|
6
7
|
PanelGroup,
|
|
7
8
|
PanelResizeHandle,
|
|
@@ -130,6 +131,65 @@ describe("PanelGroup", () => {
|
|
|
130
131
|
expect(element.title).toBe("bar");
|
|
131
132
|
});
|
|
132
133
|
|
|
134
|
+
describe("callbacks", () => {
|
|
135
|
+
describe("onLayout", () => {
|
|
136
|
+
it("should be called with the initial group layout on mount", () => {
|
|
137
|
+
let onLayout = jest.fn();
|
|
138
|
+
|
|
139
|
+
act(() => {
|
|
140
|
+
root.render(
|
|
141
|
+
<PanelGroup direction="horizontal" onLayout={onLayout}>
|
|
142
|
+
<Panel defaultSize={35} />
|
|
143
|
+
<PanelResizeHandle />
|
|
144
|
+
<Panel defaultSize={65} />
|
|
145
|
+
</PanelGroup>
|
|
146
|
+
);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
expect(onLayout).toHaveBeenCalledTimes(1);
|
|
150
|
+
expect(onLayout).toHaveBeenCalledWith([35, 65]);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it("should be called any time the group layout changes", () => {
|
|
154
|
+
let onLayout = jest.fn();
|
|
155
|
+
let panelGroupRef = createRef<ImperativePanelGroupHandle>();
|
|
156
|
+
let panelRef = createRef<ImperativePanelHandle>();
|
|
157
|
+
|
|
158
|
+
act(() => {
|
|
159
|
+
root.render(
|
|
160
|
+
<PanelGroup
|
|
161
|
+
direction="horizontal"
|
|
162
|
+
onLayout={onLayout}
|
|
163
|
+
ref={panelGroupRef}
|
|
164
|
+
>
|
|
165
|
+
<Panel defaultSize={35} ref={panelRef} />
|
|
166
|
+
<PanelResizeHandle />
|
|
167
|
+
<Panel defaultSize={65} />
|
|
168
|
+
</PanelGroup>
|
|
169
|
+
);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
onLayout.mockReset();
|
|
173
|
+
|
|
174
|
+
act(() => {
|
|
175
|
+
panelGroupRef.current?.setLayout([25, 75]);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
expect(onLayout).toHaveBeenCalledTimes(1);
|
|
179
|
+
expect(onLayout).toHaveBeenCalledWith([25, 75]);
|
|
180
|
+
|
|
181
|
+
onLayout.mockReset();
|
|
182
|
+
|
|
183
|
+
act(() => {
|
|
184
|
+
panelRef.current?.resize(50);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
expect(onLayout).toHaveBeenCalledTimes(1);
|
|
188
|
+
expect(onLayout).toHaveBeenCalledWith([50, 50]);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
|
|
133
193
|
describe("DEV warnings", () => {
|
|
134
194
|
it("should warn about unstable layouts without id and order props", () => {
|
|
135
195
|
act(() => {
|
package/src/PanelGroup.ts
CHANGED
|
@@ -16,7 +16,6 @@ import { computePanelFlexBoxStyle } from "./utils/computePanelFlexBoxStyle";
|
|
|
16
16
|
import { resetGlobalCursorStyle, setGlobalCursorStyle } from "./utils/cursor";
|
|
17
17
|
import debounce from "./utils/debounce";
|
|
18
18
|
import { determinePivotIndices } from "./utils/determinePivotIndices";
|
|
19
|
-
import { getPanelElementsForGroup } from "./utils/dom/getPanelElementsForGroup";
|
|
20
19
|
import { getResizeHandleElement } from "./utils/dom/getResizeHandleElement";
|
|
21
20
|
import { isKeyDown, isMouseEvent, isTouchEvent } from "./utils/events";
|
|
22
21
|
import { getResizeEventCursorPosition } from "./utils/getResizeEventCursorPosition";
|
|
@@ -103,6 +102,7 @@ function PanelGroupWithForwardedRef({
|
|
|
103
102
|
|
|
104
103
|
const [dragState, setDragState] = useState<DragState | null>(null);
|
|
105
104
|
const [layout, setLayout] = useState<number[]>([]);
|
|
105
|
+
const [panelDataArray, setPanelDataArray] = useState<PanelData[]>([]);
|
|
106
106
|
|
|
107
107
|
const panelIdToLastNotifiedSizeMapRef = useRef<Record<string, number>>({});
|
|
108
108
|
const panelSizeBeforeCollapseRef = useRef<Map<string, number>>(new Map());
|
|
@@ -129,9 +129,11 @@ function PanelGroupWithForwardedRef({
|
|
|
129
129
|
const eagerValuesRef = useRef<{
|
|
130
130
|
layout: number[];
|
|
131
131
|
panelDataArray: PanelData[];
|
|
132
|
+
panelDataArrayChanged: boolean;
|
|
132
133
|
}>({
|
|
133
134
|
layout,
|
|
134
135
|
panelDataArray: [],
|
|
136
|
+
panelDataArrayChanged: false,
|
|
135
137
|
});
|
|
136
138
|
|
|
137
139
|
const devWarningsRef = useRef<{
|
|
@@ -463,26 +465,7 @@ function PanelGroupWithForwardedRef({
|
|
|
463
465
|
}, []);
|
|
464
466
|
|
|
465
467
|
const registerPanel = useCallback((panelData: PanelData) => {
|
|
466
|
-
const {
|
|
467
|
-
autoSaveId,
|
|
468
|
-
id: groupId,
|
|
469
|
-
onLayout,
|
|
470
|
-
storage,
|
|
471
|
-
} = committedValuesRef.current;
|
|
472
|
-
const { layout: prevLayout, panelDataArray } = eagerValuesRef.current;
|
|
473
|
-
|
|
474
|
-
// HACK
|
|
475
|
-
// This appears to be triggered by some React Suspense+Offscreen+StrictMode bug;
|
|
476
|
-
// see app.replay.io/recording/17b6e11d-4500-4173-b23d-61dfd141fed1
|
|
477
|
-
const index = findPanelDataIndex(panelDataArray, panelData);
|
|
478
|
-
if (index >= 0) {
|
|
479
|
-
if (panelData.idIsFromProps) {
|
|
480
|
-
console.warn(`Panel with id "${panelData.id}" registered twice`);
|
|
481
|
-
} else {
|
|
482
|
-
console.warn(`Panel registered twice`);
|
|
483
|
-
}
|
|
484
|
-
return;
|
|
485
|
-
}
|
|
468
|
+
const { panelDataArray } = eagerValuesRef.current;
|
|
486
469
|
|
|
487
470
|
panelDataArray.push(panelData);
|
|
488
471
|
panelDataArray.sort((panelA, panelB) => {
|
|
@@ -499,54 +482,57 @@ function PanelGroupWithForwardedRef({
|
|
|
499
482
|
}
|
|
500
483
|
});
|
|
501
484
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
const panelElements = getPanelElementsForGroup(groupId);
|
|
505
|
-
if (panelElements.length !== panelDataArray.length) {
|
|
506
|
-
return;
|
|
507
|
-
}
|
|
485
|
+
eagerValuesRef.current.panelDataArrayChanged = true;
|
|
486
|
+
}, []);
|
|
508
487
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
if (
|
|
513
|
-
|
|
514
|
-
}
|
|
488
|
+
// (Re)calculate group layout whenever panels are registered or unregistered.
|
|
489
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
490
|
+
useIsomorphicLayoutEffect(() => {
|
|
491
|
+
if (eagerValuesRef.current.panelDataArrayChanged) {
|
|
492
|
+
eagerValuesRef.current.panelDataArrayChanged = false;
|
|
515
493
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
494
|
+
const { autoSaveId, onLayout, storage } = committedValuesRef.current;
|
|
495
|
+
const { layout: prevLayout, panelDataArray } = eagerValuesRef.current;
|
|
496
|
+
|
|
497
|
+
// If this panel has been configured to persist sizing information,
|
|
498
|
+
// default size should be restored from local storage if possible.
|
|
499
|
+
let unsafeLayout: number[] | null = null;
|
|
500
|
+
if (autoSaveId) {
|
|
501
|
+
unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
if (unsafeLayout == null) {
|
|
505
|
+
unsafeLayout = calculateUnsafeDefaultLayout({
|
|
506
|
+
panelDataArray,
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// Validate even saved layouts in case something has changed since last render
|
|
511
|
+
// e.g. for pixel groups, this could be the size of the window
|
|
512
|
+
const nextLayout = validatePanelGroupLayout({
|
|
513
|
+
layout: unsafeLayout,
|
|
514
|
+
panelConstraints: panelDataArray.map(
|
|
515
|
+
(panelData) => panelData.constraints
|
|
516
|
+
),
|
|
519
517
|
});
|
|
520
|
-
}
|
|
521
518
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
const nextLayout = validatePanelGroupLayout({
|
|
525
|
-
layout: unsafeLayout,
|
|
526
|
-
panelConstraints: panelDataArray.map(
|
|
527
|
-
(panelData) => panelData.constraints
|
|
528
|
-
),
|
|
529
|
-
});
|
|
519
|
+
if (!areEqual(prevLayout, nextLayout)) {
|
|
520
|
+
setLayout(nextLayout);
|
|
530
521
|
|
|
531
|
-
|
|
532
|
-
// Panels unregister when hidden and re-register when shown again,
|
|
533
|
-
// but the overall layout doesn't change between these two cases.
|
|
534
|
-
setLayout(nextLayout);
|
|
522
|
+
eagerValuesRef.current.layout = nextLayout;
|
|
535
523
|
|
|
536
|
-
|
|
524
|
+
if (onLayout) {
|
|
525
|
+
onLayout(nextLayout);
|
|
526
|
+
}
|
|
537
527
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
528
|
+
callPanelCallbacks(
|
|
529
|
+
panelDataArray,
|
|
530
|
+
nextLayout,
|
|
531
|
+
panelIdToLastNotifiedSizeMapRef.current
|
|
532
|
+
);
|
|
541
533
|
}
|
|
542
|
-
|
|
543
|
-
callPanelCallbacks(
|
|
544
|
-
panelDataArray,
|
|
545
|
-
nextLayout,
|
|
546
|
-
panelIdToLastNotifiedSizeMapRef.current
|
|
547
|
-
);
|
|
548
534
|
}
|
|
549
|
-
}
|
|
535
|
+
});
|
|
550
536
|
|
|
551
537
|
const registerResizeHandle = useCallback((dragHandleId: string) => {
|
|
552
538
|
return function resizeHandler(event: ResizeEvent) {
|
|
@@ -723,90 +709,21 @@ function PanelGroupWithForwardedRef({
|
|
|
723
709
|
setDragState(null);
|
|
724
710
|
}, []);
|
|
725
711
|
|
|
726
|
-
const unregisterPanelRef = useRef<{
|
|
727
|
-
pendingPanelIds: Set<string>;
|
|
728
|
-
timeout: NodeJS.Timeout | null;
|
|
729
|
-
}>({
|
|
730
|
-
pendingPanelIds: new Set(),
|
|
731
|
-
timeout: null,
|
|
732
|
-
});
|
|
733
712
|
const unregisterPanel = useCallback((panelData: PanelData) => {
|
|
734
|
-
const {
|
|
735
|
-
const { layout: prevLayout, panelDataArray } = eagerValuesRef.current;
|
|
713
|
+
const { panelDataArray } = eagerValuesRef.current;
|
|
736
714
|
|
|
737
715
|
const index = findPanelDataIndex(panelDataArray, panelData);
|
|
738
716
|
if (index >= 0) {
|
|
739
717
|
panelDataArray.splice(index, 1);
|
|
740
|
-
unregisterPanelRef.current.pendingPanelIds.add(panelData.id);
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
if (unregisterPanelRef.current.timeout != null) {
|
|
744
|
-
clearTimeout(unregisterPanelRef.current.timeout);
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
// Batch panel unmounts so that we only calculate layout once;
|
|
748
|
-
// This is more efficient and avoids misleading warnings in development mode.
|
|
749
|
-
// We can't check the DOM to detect this because Panel elements have not yet been removed.
|
|
750
|
-
unregisterPanelRef.current.timeout = setTimeout(() => {
|
|
751
|
-
const { pendingPanelIds } = unregisterPanelRef.current;
|
|
752
|
-
const panelIdToLastNotifiedSizeMap =
|
|
753
|
-
panelIdToLastNotifiedSizeMapRef.current;
|
|
754
718
|
|
|
755
719
|
// TRICKY
|
|
756
|
-
//
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
if (panelDataArray.find(({ id }) => id === panelId) != null) {
|
|
762
|
-
unmountDueToStrictMode = true;
|
|
763
|
-
} else {
|
|
764
|
-
// TRICKY
|
|
765
|
-
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
766
|
-
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
767
|
-
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
768
|
-
delete panelIdToLastNotifiedSizeMap[panelId];
|
|
769
|
-
}
|
|
770
|
-
});
|
|
771
|
-
|
|
772
|
-
if (unmountDueToStrictMode) {
|
|
773
|
-
return;
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
if (panelDataArray.length === 0) {
|
|
777
|
-
// The group is unmounting; skip layout calculation.
|
|
778
|
-
return;
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
let unsafeLayout: number[] = calculateUnsafeDefaultLayout({
|
|
782
|
-
panelDataArray,
|
|
783
|
-
});
|
|
720
|
+
// When a panel is removed from the group, we should delete the most recent prev-size entry for it.
|
|
721
|
+
// If we don't do this, then a conditionally rendered panel might not call onResize when it's re-mounted.
|
|
722
|
+
// Strict effects mode makes this tricky though because all panels will be registered, unregistered, then re-registered on mount.
|
|
723
|
+
delete panelIdToLastNotifiedSizeMapRef.current[panelData.id];
|
|
784
724
|
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
const nextLayout = validatePanelGroupLayout({
|
|
788
|
-
layout: unsafeLayout,
|
|
789
|
-
panelConstraints: panelDataArray.map(
|
|
790
|
-
(panelData) => panelData.constraints
|
|
791
|
-
),
|
|
792
|
-
});
|
|
793
|
-
|
|
794
|
-
if (!areEqual(prevLayout, nextLayout)) {
|
|
795
|
-
setLayout(nextLayout);
|
|
796
|
-
|
|
797
|
-
eagerValuesRef.current.layout = nextLayout;
|
|
798
|
-
|
|
799
|
-
if (onLayout) {
|
|
800
|
-
onLayout(nextLayout);
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
callPanelCallbacks(
|
|
804
|
-
panelDataArray,
|
|
805
|
-
nextLayout,
|
|
806
|
-
panelIdToLastNotifiedSizeMapRef.current
|
|
807
|
-
);
|
|
808
|
-
}
|
|
809
|
-
}, 0);
|
|
725
|
+
eagerValuesRef.current.panelDataArrayChanged = true;
|
|
726
|
+
}
|
|
810
727
|
}, []);
|
|
811
728
|
|
|
812
729
|
const context = useMemo(
|
|
@@ -65,4 +65,10 @@ describe("PanelResizeHandle", () => {
|
|
|
65
65
|
expect(element.getAttribute("data-test-name")).toBe("foo");
|
|
66
66
|
expect(element.title).toBe("bar");
|
|
67
67
|
});
|
|
68
|
+
|
|
69
|
+
describe("callbacks", () => {
|
|
70
|
+
describe("onDragging", () => {
|
|
71
|
+
// TODO: Test this
|
|
72
|
+
});
|
|
73
|
+
});
|
|
68
74
|
});
|