react-resizable-panels 0.0.56 → 0.0.58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/declarations/src/Panel.d.ts +7 -3
  3. package/dist/declarations/src/PanelGroup.d.ts +3 -1
  4. package/dist/declarations/src/PanelResizeHandle.d.ts +3 -1
  5. package/dist/declarations/src/types.d.ts +3 -0
  6. package/dist/react-resizable-panels.browser.cjs.js +186 -87
  7. package/dist/react-resizable-panels.browser.development.cjs.js +186 -87
  8. package/dist/react-resizable-panels.browser.development.esm.js +186 -87
  9. package/dist/react-resizable-panels.browser.esm.js +186 -87
  10. package/dist/react-resizable-panels.cjs.js +186 -87
  11. package/dist/react-resizable-panels.cjs.js.map +1 -1
  12. package/dist/react-resizable-panels.development.cjs.js +186 -87
  13. package/dist/react-resizable-panels.development.esm.js +186 -87
  14. package/dist/react-resizable-panels.development.node.cjs.js +175 -82
  15. package/dist/react-resizable-panels.development.node.esm.js +175 -82
  16. package/dist/react-resizable-panels.esm.js +186 -87
  17. package/dist/react-resizable-panels.esm.js.map +1 -1
  18. package/dist/react-resizable-panels.node.cjs.js +175 -82
  19. package/dist/react-resizable-panels.node.esm.js +175 -82
  20. package/package.json +3 -1
  21. package/src/Panel.ts +9 -3
  22. package/src/PanelGroup.ts +11 -5
  23. package/src/PanelResizeHandle.ts +17 -13
  24. package/src/types.ts +4 -0
  25. package/src/utils/adjustLayoutByDelta.test.ts +238 -8
  26. package/src/utils/adjustLayoutByDelta.ts +122 -72
  27. package/src/utils/computePercentagePanelConstraints.test.ts +27 -0
  28. package/src/utils/convertPixelConstraintsToPercentages.test.ts +47 -0
  29. package/src/utils/convertPixelConstraintsToPercentages.ts +17 -0
  30. package/src/utils/dom/getPanelGroupElement.ts +3 -1
  31. package/src/utils/resizePanel.test.ts +105 -0
  32. package/src/utils/resizePanel.ts +26 -1
  33. package/src/utils/validatePanelGroupLayout.test.ts +36 -6
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.0.58
4
+
5
+ - Change group layout to more thoroughly distribute resize delta to support more flexible group size configurations.
6
+ - Add data attribute support to `Panel`, `PanelGroup`, and `PanelResizeHandle`.
7
+ - Update API documentation to reflect changed imperative API method names.
8
+ - `PanelOnResize` TypeScript def updated to reflect that previous size param is `undefined` the first time it is called.
9
+
10
+ ## 0.0.57
11
+
12
+ - [#207](https://github.com/bvaughn/react-resizable-panels/pull/207): Fix DEV conditional error that broke data attributes (and selectors).
13
+
3
14
  ## 0.0.56
4
15
 
5
16
  Support a mix of percentage and pixel based units at the `Panel` level:
@@ -1,8 +1,8 @@
1
- import { MixedSizes } from "./types.js";
1
+ import { DataAttributes, MixedSizes } from "./types.js";
2
2
  import { ElementType, ForwardedRef, PropsWithChildren } from "./vendor/react.js";
3
3
  export type PanelOnCollapse = () => void;
4
4
  export type PanelOnExpand = () => void;
5
- export type PanelOnResize = (mixedSizes: MixedSizes, prevMixedSizes: MixedSizes) => void;
5
+ export type PanelOnResize = (mixedSizes: MixedSizes, prevMixedSizes: MixedSizes | undefined) => void;
6
6
  export type PanelCallbacks = {
7
7
  onCollapse?: PanelOnCollapse;
8
8
  onExpand?: PanelOnExpand;
@@ -31,6 +31,8 @@ export type ImperativePanelHandle = {
31
31
  expand: () => void;
32
32
  getId(): string;
33
33
  getSize(): MixedSizes;
34
+ isCollapsed: () => boolean;
35
+ isExpanded: () => boolean;
34
36
  resize: (size: Partial<MixedSizes>) => void;
35
37
  };
36
38
  export type PanelProps = PropsWithChildren<{
@@ -38,6 +40,7 @@ export type PanelProps = PropsWithChildren<{
38
40
  collapsedSizePercentage?: number | undefined;
39
41
  collapsedSizePixels?: number | undefined;
40
42
  collapsible?: boolean | undefined;
43
+ dataAttributes?: DataAttributes;
41
44
  defaultSizePercentage?: number | undefined;
42
45
  defaultSizePixels?: number | undefined;
43
46
  id?: string;
@@ -52,7 +55,7 @@ export type PanelProps = PropsWithChildren<{
52
55
  style?: object;
53
56
  tagName?: ElementType;
54
57
  }>;
55
- export declare function PanelWithForwardedRef({ children, className: classNameFromProps, collapsedSizePercentage, collapsedSizePixels, collapsible, defaultSizePercentage, defaultSizePixels, forwardedRef, id: idFromProps, maxSizePercentage, maxSizePixels, minSizePercentage, minSizePixels, onCollapse, onExpand, onResize, order, style: styleFromProps, tagName: Type, }: PanelProps & {
58
+ export declare function PanelWithForwardedRef({ children, className: classNameFromProps, collapsedSizePercentage, collapsedSizePixels, collapsible, dataAttributes, defaultSizePercentage, defaultSizePixels, forwardedRef, id: idFromProps, maxSizePercentage, maxSizePixels, minSizePercentage, minSizePixels, onCollapse, onExpand, onResize, order, style: styleFromProps, tagName: Type, }: PanelProps & {
56
59
  forwardedRef: ForwardedRef<ImperativePanelHandle>;
57
60
  }): import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
58
61
  export declare namespace PanelWithForwardedRef {
@@ -63,6 +66,7 @@ export declare const Panel: import("react").ForwardRefExoticComponent<{
63
66
  collapsedSizePercentage?: number | undefined;
64
67
  collapsedSizePixels?: number | undefined;
65
68
  collapsible?: boolean | undefined;
69
+ dataAttributes?: DataAttributes | undefined;
66
70
  defaultSizePercentage?: number | undefined;
67
71
  defaultSizePixels?: number | undefined;
68
72
  id?: string | undefined;
@@ -1,4 +1,4 @@
1
- import { Direction, MixedSizes } from "./types.js";
1
+ import { DataAttributes, Direction, MixedSizes } from "./types.js";
2
2
  import { CSSProperties, ElementType, PropsWithChildren } from "./vendor/react.js";
3
3
  export type ImperativePanelGroupHandle = {
4
4
  getId: () => string;
@@ -13,6 +13,7 @@ export type PanelGroupOnLayout = (layout: MixedSizes[]) => void;
13
13
  export type PanelGroupProps = PropsWithChildren<{
14
14
  autoSaveId?: string;
15
15
  className?: string;
16
+ dataAttributes?: DataAttributes;
16
17
  direction: Direction;
17
18
  id?: string | null;
18
19
  keyboardResizeByPercentage?: number | null;
@@ -25,6 +26,7 @@ export type PanelGroupProps = PropsWithChildren<{
25
26
  export declare const PanelGroup: import("react").ForwardRefExoticComponent<{
26
27
  autoSaveId?: string | undefined;
27
28
  className?: string | undefined;
29
+ dataAttributes?: DataAttributes | undefined;
28
30
  direction: Direction;
29
31
  id?: string | null | undefined;
30
32
  keyboardResizeByPercentage?: number | null | undefined;
@@ -1,15 +1,17 @@
1
1
  import { CSSProperties, ElementType, ReactNode } from "./vendor/react.js";
2
+ import { DataAttributes } from "./types.js";
2
3
  export type PanelResizeHandleOnDragging = (isDragging: boolean) => void;
3
4
  export type PanelResizeHandleProps = {
4
5
  children?: ReactNode;
5
6
  className?: string;
7
+ dataAttributes?: DataAttributes;
6
8
  disabled?: boolean;
7
9
  id?: string | null;
8
10
  onDragging?: PanelResizeHandleOnDragging;
9
11
  style?: CSSProperties;
10
12
  tagName?: ElementType;
11
13
  };
12
- export declare function PanelResizeHandle({ children, className: classNameFromProps, disabled, id: idFromProps, onDragging, style: styleFromProps, tagName: Type, }: PanelResizeHandleProps): import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
14
+ export declare function PanelResizeHandle({ children, className: classNameFromProps, dataAttributes, disabled, id: idFromProps, onDragging, style: styleFromProps, tagName: Type, }: PanelResizeHandleProps): import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
13
15
  export declare namespace PanelResizeHandle {
14
16
  var displayName: string;
15
17
  }
@@ -5,3 +5,6 @@ export type MixedSizes = {
5
5
  };
6
6
  export type ResizeEvent = KeyboardEvent | MouseEvent | TouchEvent;
7
7
  export type ResizeHandler = (event: ResizeEvent) => void;
8
+ export type DataAttributes = {
9
+ [attribute: string]: string | number | boolean | undefined;
10
+ };
@@ -59,7 +59,7 @@ function useUniqueId(idFromParams = null) {
59
59
  if (idRef.current === null) {
60
60
  idRef.current = "" + counter++;
61
61
  }
62
- return idFromParams ?? idRef.current;
62
+ return idFromParams !== null && idFromParams !== void 0 ? idFromParams : idRef.current;
63
63
  }
64
64
 
65
65
  function PanelWithForwardedRef({
@@ -68,6 +68,7 @@ function PanelWithForwardedRef({
68
68
  collapsedSizePercentage,
69
69
  collapsedSizePixels,
70
70
  collapsible,
71
+ dataAttributes,
71
72
  defaultSizePercentage,
72
73
  defaultSizePixels,
73
74
  forwardedRef,
@@ -181,11 +182,12 @@ function PanelWithForwardedRef({
181
182
  ...style,
182
183
  ...styleFromProps
183
184
  },
185
+ ...dataAttributes,
184
186
  // CSS selectors
185
187
  "data-panel": "",
188
+ "data-panel-id": panelId,
186
189
  // e2e test attributes
187
190
  "data-panel-collapsible": undefined,
188
- "data-panel-id": undefined,
189
191
  "data-panel-size": undefined
190
192
  });
191
193
  }
@@ -213,6 +215,16 @@ function convertPixelConstraintsToPercentages(panelConstraints, groupSizePixels)
213
215
  minSizePercentage = 0,
214
216
  minSizePixels
215
217
  } = panelConstraints;
218
+ const hasPixelConstraints = collapsedSizePixels != null || defaultSizePixels != null || minSizePixels != null || maxSizePixels != null;
219
+ if (hasPixelConstraints && groupSizePixels <= 0) {
220
+ console.warn(`WARNING: Invalid group size: ${groupSizePixels}px`);
221
+ return {
222
+ collapsedSizePercentage: 0,
223
+ defaultSizePercentage,
224
+ maxSizePercentage: 0,
225
+ minSizePercentage: 0
226
+ };
227
+ }
216
228
  if (collapsedSizePixels != null) {
217
229
  collapsedSizePercentage = convertPixelsToPercentage(collapsedSizePixels, groupSizePixels);
218
230
  }
@@ -287,6 +299,16 @@ function resizePanel({
287
299
  panelIndex,
288
300
  size
289
301
  }) {
302
+ const hasPixelConstraints = panelConstraints.some(({
303
+ collapsedSizePixels,
304
+ defaultSizePixels,
305
+ minSizePixels,
306
+ maxSizePixels
307
+ }) => collapsedSizePixels != null || defaultSizePixels != null || minSizePixels != null || maxSizePixels != null);
308
+ if (hasPixelConstraints && groupSizePixels <= 0) {
309
+ console.warn(`WARNING: Invalid group size: ${groupSizePixels}px`);
310
+ return 0;
311
+ }
290
312
  let {
291
313
  collapsible
292
314
  } = panelConstraints[panelIndex];
@@ -298,7 +320,13 @@ function resizePanel({
298
320
  if (minSizePercentage != null) {
299
321
  if (fuzzyCompareNumbers(size, minSizePercentage) < 0) {
300
322
  if (collapsible) {
301
- size = collapsedSizePercentage;
323
+ // Collapsible panels should snap closed or open only once they cross the halfway point between collapsed and min size.
324
+ const halfwayPoint = (collapsedSizePercentage + minSizePercentage) / 2;
325
+ if (fuzzyCompareNumbers(size, halfwayPoint) < 0) {
326
+ size = collapsedSizePercentage;
327
+ } else {
328
+ size = minSizePercentage;
329
+ }
302
330
  } else {
303
331
  size = minSizePercentage;
304
332
  }
@@ -325,61 +353,123 @@ function adjustLayoutByDelta({
325
353
  const nextLayout = [...prevLayout];
326
354
  let deltaApplied = 0;
327
355
 
356
+ //const DEBUG = [];
357
+ //DEBUG.push(`adjustLayoutByDelta() ${prevLayout.join(", ")}`);
358
+ //DEBUG.push(` delta: ${delta}`);
359
+ //DEBUG.push(` pivotIndices: ${pivotIndices.join(", ")}`);
360
+ //DEBUG.push(` trigger: ${trigger}`);
361
+ //DEBUG.push("");
362
+
328
363
  // A resizing panel affects the panels before or after it.
329
364
  //
330
- // A negative delta means the panel immediately after the resizer should grow/expand by decreasing its offset.
365
+ // A negative delta means the panel(s) immediately after the resize handle should grow/expand by decreasing its offset.
331
366
  // Other panels may also need to shrink/contract (and shift) to make room, depending on the min weights.
332
367
  //
333
- // A positive delta means the panel immediately before the resizer should "expand".
334
- // This is accomplished by shrinking/contracting (and shifting) one or more of the panels after the resizer.
368
+ // A positive delta means the panel(s) immediately before the resize handle should "expand".
369
+ // This is accomplished by shrinking/contracting (and shifting) one or more of the panels after the resize handle.
335
370
 
336
- // First, check the panel we're pivoting around;
337
- // We should only expand or contract by as much as its constraints allow
338
371
  {
339
- const pivotIndex = delta < 0 ? pivotIndices[1] : pivotIndices[0];
340
- const initialSize = nextLayout[pivotIndex];
341
- const {
342
- collapsible
343
- } = panelConstraints[pivotIndex];
344
- const {
345
- collapsedSizePercentage,
346
- maxSizePercentage,
347
- minSizePercentage
348
- } = computePercentagePanelConstraints(panelConstraints, pivotIndex, groupSizePixels);
349
- const isCollapsed = collapsible && fuzzyNumbersEqual(initialSize, collapsedSizePercentage);
350
- let unsafeSize = initialSize + Math.abs(delta);
351
- if (isCollapsed) {
352
- switch (trigger) {
353
- case "keyboard":
354
- if (minSizePercentage > unsafeSize) {
355
- unsafeSize = minSizePercentage;
372
+ // If this is a resize triggered by a keyboard event, our logic for expanding/collapsing is different.
373
+ // We no longer check the halfway threshold because this may prevent the panel from expanding at all.
374
+ if (trigger === "keyboard") {
375
+ {
376
+ // Check if we should expand a collapsed panel
377
+ const index = delta < 0 ? pivotIndices[1] : pivotIndices[0];
378
+ const constraints = panelConstraints[index];
379
+ //DEBUG.push(`edge case check 1: ${index}`);
380
+ //DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
381
+ if (constraints.collapsible) {
382
+ const prevSize = prevLayout[index];
383
+ const {
384
+ collapsedSizePercentage,
385
+ minSizePercentage
386
+ } = computePercentagePanelConstraints(panelConstraints, index, groupSizePixels);
387
+ if (fuzzyNumbersEqual(prevSize, collapsedSizePercentage)) {
388
+ const localDelta = minSizePercentage - prevSize;
389
+ //DEBUG.push(` -> expand delta: ${localDelta}`);
390
+
391
+ if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
392
+ delta = delta < 0 ? 0 - localDelta : localDelta;
393
+ //DEBUG.push(` -> delta: ${delta}`);
394
+ }
356
395
  }
396
+ }
397
+ }
398
+
399
+ {
400
+ // Check if we should collapse a panel at its minimum size
401
+ const index = delta < 0 ? pivotIndices[0] : pivotIndices[1];
402
+ const constraints = panelConstraints[index];
403
+ //DEBUG.push(`edge case check 2: ${index}`);
404
+ //DEBUG.push(` -> collapsible? ${constraints.collapsible}`);
405
+ if (constraints.collapsible) {
406
+ const prevSize = prevLayout[index];
407
+ const {
408
+ collapsedSizePercentage,
409
+ minSizePercentage
410
+ } = computePercentagePanelConstraints(panelConstraints, index, groupSizePixels);
411
+ if (fuzzyNumbersEqual(prevSize, minSizePercentage)) {
412
+ const localDelta = prevSize - collapsedSizePercentage;
413
+ //DEBUG.push(` -> expand delta: ${localDelta}`);
414
+
415
+ if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0) {
416
+ delta = delta < 0 ? 0 - localDelta : localDelta;
417
+ //DEBUG.push(` -> delta: ${delta}`);
418
+ }
419
+ }
420
+ }
357
421
  }
358
422
  }
359
- const safeSize = resizePanel({
360
- groupSizePixels,
361
- panelConstraints,
362
- panelIndex: pivotIndex,
363
- size: unsafeSize
364
- });
365
- if (fuzzyNumbersEqual(initialSize, safeSize)) {
366
- // If there's no room for the pivot panel to grow, we should ignore this change
367
- return nextLayout;
368
- } else {
369
- delta = delta < 0 ? initialSize - safeSize : safeSize - initialSize;
423
+ //DEBUG.push("");
424
+ }
425
+
426
+ {
427
+ // Pre-calculate max available delta in the opposite direction of our pivot.
428
+ // This will be the maximum amount we're allowed to expand/contract the panels in the primary direction.
429
+ // If this amount is less than the requested delta, adjust the requested delta.
430
+ // If this amount is greater than the requested delta, that's useful information too–
431
+ // as an expanding panel might change from collapsed to min size.
432
+
433
+ const increment = delta < 0 ? 1 : -1;
434
+ let index = delta < 0 ? pivotIndices[1] : pivotIndices[0];
435
+ let maxAvailableDelta = 0;
436
+
437
+ //DEBUG.push("pre calc...");
438
+ while (true) {
439
+ const prevSize = prevLayout[index];
440
+ const maxSafeSize = resizePanel({
441
+ groupSizePixels,
442
+ panelConstraints,
443
+ panelIndex: index,
444
+ size: 100
445
+ });
446
+ const delta = maxSafeSize - prevSize;
447
+ //DEBUG.push(` ${index}: ${prevSize} -> ${maxSafeSize}`);
448
+
449
+ maxAvailableDelta += delta;
450
+ index += increment;
451
+ if (index < 0 || index >= panelConstraints.length) {
452
+ break;
453
+ }
370
454
  }
455
+
456
+ //DEBUG.push(` -> max available delta: ${maxAvailableDelta}`);
457
+ const minAbsDelta = Math.min(Math.abs(delta), Math.abs(maxAvailableDelta));
458
+ delta = delta < 0 ? 0 - minAbsDelta : minAbsDelta;
459
+ //DEBUG.push(` -> adjusted delta: ${delta}`);
460
+ //DEBUG.push("");
371
461
  }
372
462
 
373
- // Delta added to a panel needs to be subtracted from other panels
374
- // within the constraints that those panels allow
375
463
  {
464
+ // Delta added to a panel needs to be subtracted from other panels (within the constraints that those panels allow).
465
+
376
466
  const pivotIndex = delta < 0 ? pivotIndices[0] : pivotIndices[1];
377
467
  let index = pivotIndex;
378
468
  while (index >= 0 && index < panelConstraints.length) {
379
469
  const deltaRemaining = Math.abs(delta) - Math.abs(deltaApplied);
380
470
  const prevSize = prevLayout[index];
381
471
  const unsafeSize = prevSize - deltaRemaining;
382
- let safeSize = resizePanel({
472
+ const safeSize = resizePanel({
383
473
  groupSizePixels,
384
474
  panelConstraints,
385
475
  panelIndex: index,
@@ -401,13 +491,18 @@ function adjustLayoutByDelta({
401
491
  }
402
492
  }
403
493
  }
494
+ //DEBUG.push(`after 1: ${nextLayout.join(", ")}`);
495
+ //DEBUG.push(` deltaApplied: ${deltaApplied}`);
496
+ //DEBUG.push("");
404
497
 
405
498
  // If we were unable to resize any of the panels panels, return the previous state.
406
499
  // This will essentially bailout and ignore e.g. drags past a panel's boundaries
407
500
  if (fuzzyNumbersEqual(deltaApplied, 0)) {
501
+ //console.log(DEBUG.join("\n"));
408
502
  return prevLayout;
409
503
  }
410
504
  {
505
+ // Now distribute the applied delta to the panels in the other direction
411
506
  const pivotIndex = delta < 0 ? pivotIndices[1] : pivotIndices[0];
412
507
  const unsafeSize = prevLayout[pivotIndex] + deltaApplied;
413
508
  const safeSize = resizePanel({
@@ -447,29 +542,21 @@ function adjustLayoutByDelta({
447
542
  index++;
448
543
  }
449
544
  }
450
-
451
- // If we can't redistribute, this layout is invalid;
452
- // There may be an incremental layout that is valid though
453
- if (!fuzzyNumbersEqual(deltaRemaining, 0)) {
454
- try {
455
- return adjustLayoutByDelta({
456
- delta: delta < 0 ? delta + 1 : delta - 1,
457
- groupSizePixels,
458
- layout: prevLayout,
459
- panelConstraints,
460
- pivotIndices,
461
- trigger
462
- });
463
- } catch (error) {
464
- if (error instanceof RangeError) {
465
- console.error(`Could not apply delta ${delta} to layout`);
466
- return prevLayout;
467
- }
468
- } finally {
469
- }
470
- }
471
545
  }
472
546
  }
547
+ //DEBUG.push(`after 2: ${nextLayout.join(", ")}`);
548
+ //DEBUG.push(` deltaApplied: ${deltaApplied}`);
549
+ //DEBUG.push("");
550
+
551
+ const totalSize = nextLayout.reduce((total, size) => size + total, 0);
552
+ deltaApplied = 100 - totalSize;
553
+ //DEBUG.push(`total size: ${totalSize}`);
554
+ //DEBUG.push(` deltaApplied: ${deltaApplied}`);
555
+ //console.log(DEBUG.join("\n"));
556
+
557
+ if (!fuzzyNumbersEqual(totalSize, 100)) {
558
+ return prevLayout;
559
+ }
473
560
  return nextLayout;
474
561
  }
475
562
 
@@ -505,6 +592,7 @@ function calculateAriaValues({
505
592
 
506
593
  // A panel's effective min/max sizes also need to account for other panel's sizes.
507
594
  panelsArray.forEach((panelData, index) => {
595
+ var _getPercentageSizeFro, _getPercentageSizeFro2;
508
596
  const {
509
597
  constraints
510
598
  } = panelData;
@@ -514,14 +602,14 @@ function calculateAriaValues({
514
602
  minSizePercentage,
515
603
  minSizePixels
516
604
  } = constraints;
517
- const minSize = getPercentageSizeFromMixedSizes({
605
+ const minSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
518
606
  sizePercentage: minSizePercentage,
519
607
  sizePixels: minSizePixels
520
- }, groupSizePixels) ?? 0;
521
- const maxSize = getPercentageSizeFromMixedSizes({
608
+ }, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
609
+ const maxSize = (_getPercentageSizeFro2 = getPercentageSizeFromMixedSizes({
522
610
  sizePercentage: maxSizePercentage,
523
611
  sizePixels: maxSizePixels
524
- }, groupSizePixels) ?? 100;
612
+ }, groupSizePixels)) !== null && _getPercentageSizeFro2 !== void 0 ? _getPercentageSizeFro2 : 100;
525
613
  if (index === pivotIndices[0]) {
526
614
  currentMinSize = minSize;
527
615
  currentMaxSize = maxSize;
@@ -547,7 +635,7 @@ function getResizeHandleElementsForGroup(groupId) {
547
635
  function getResizeHandleElementIndex(groupId, id) {
548
636
  const handles = getResizeHandleElementsForGroup(groupId);
549
637
  const index = handles.findIndex(handle => handle.getAttribute("data-panel-resize-handle-id") === id);
550
- return index ?? null;
638
+ return index !== null && index !== void 0 ? index : null;
551
639
  }
552
640
 
553
641
  function determinePivotIndices(groupId, dragHandleId) {
@@ -556,7 +644,7 @@ function determinePivotIndices(groupId, dragHandleId) {
556
644
  }
557
645
 
558
646
  function getPanelGroupElement(id) {
559
- const element = document.querySelector(`[data-panel-group-id="${id}"]`);
647
+ const element = document.querySelector(`[data-panel-group][data-panel-group-id="${id}"]`);
560
648
  if (element) {
561
649
  return element;
562
650
  }
@@ -608,11 +696,12 @@ function getResizeHandleElement(id) {
608
696
  }
609
697
 
610
698
  function getResizeHandlePanelIds(groupId, handleId, panelsArray) {
699
+ var _panelsArray$index$id, _panelsArray$index, _panelsArray$id, _panelsArray;
611
700
  const handle = getResizeHandleElement(handleId);
612
701
  const handles = getResizeHandleElementsForGroup(groupId);
613
702
  const index = handle ? handles.indexOf(handle) : -1;
614
- const idBefore = panelsArray[index]?.id ?? null;
615
- const idAfter = panelsArray[index + 1]?.id ?? null;
703
+ const idBefore = (_panelsArray$index$id = (_panelsArray$index = panelsArray[index]) === null || _panelsArray$index === void 0 ? void 0 : _panelsArray$index.id) !== null && _panelsArray$index$id !== void 0 ? _panelsArray$index$id : null;
704
+ const idAfter = (_panelsArray$id = (_panelsArray = panelsArray[index + 1]) === null || _panelsArray === void 0 ? void 0 : _panelsArray.id) !== null && _panelsArray$id !== void 0 ? _panelsArray$id : null;
616
705
  return [idBefore, idAfter];
617
706
  }
618
707
 
@@ -690,11 +779,12 @@ function useWindowSplitterPanelGroupBehavior({
690
779
  const panelData = panelDataArray[index];
691
780
  const size = layout[index];
692
781
  if (size != null) {
782
+ var _getPercentageSizeFro;
693
783
  const groupSizePixels = getAvailableGroupSizePixels(groupId);
694
- const minSize = getPercentageSizeFromMixedSizes({
784
+ const minSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
695
785
  sizePercentage: panelData.constraints.minSizePercentage,
696
786
  sizePixels: panelData.constraints.minSizePixels
697
- }, groupSizePixels) ?? 0;
787
+ }, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
698
788
  let delta = 0;
699
789
  if (size.toPrecision(PRECISION) <= minSize.toPrecision(PRECISION)) {
700
790
  delta = direction === "horizontal" ? width : height;
@@ -899,10 +989,11 @@ function callPanelCallbacks(groupId, panelsArray, layout, panelIdToLastNotifiedM
899
989
  onResize(mixedSizes, lastNotifiedMixedSizes);
900
990
  }
901
991
  if (collapsible && (onCollapse || onExpand)) {
902
- const collapsedSize = getPercentageSizeFromMixedSizes({
992
+ var _getPercentageSizeFro;
993
+ const collapsedSize = (_getPercentageSizeFro = getPercentageSizeFromMixedSizes({
903
994
  sizePercentage: constraints.collapsedSizePercentage,
904
995
  sizePixels: constraints.collapsedSizePixels
905
- }, groupSizePixels) ?? 0;
996
+ }, groupSizePixels)) !== null && _getPercentageSizeFro !== void 0 ? _getPercentageSizeFro : 0;
906
997
  const size = getPercentageSizeFromMixedSizes(mixedSizes, groupSizePixels);
907
998
  if (onExpand && (lastNotifiedMixedSizes == null || lastNotifiedMixedSizes.sizePercentage === collapsedSize) && size !== collapsedSize) {
908
999
  onExpand();
@@ -1068,8 +1159,9 @@ function loadSerializedPanelGroupState(autoSaveId, storage) {
1068
1159
  function loadPanelLayout(autoSaveId, panels, storage) {
1069
1160
  const state = loadSerializedPanelGroupState(autoSaveId, storage);
1070
1161
  if (state) {
1162
+ var _state$key;
1071
1163
  const key = getSerializationKey(panels);
1072
- return state[key] ?? null;
1164
+ return (_state$key = state[key]) !== null && _state$key !== void 0 ? _state$key : null;
1073
1165
  }
1074
1166
  return null;
1075
1167
  }
@@ -1161,6 +1253,7 @@ function PanelGroupWithForwardedRef({
1161
1253
  autoSaveId,
1162
1254
  children,
1163
1255
  className: classNameFromProps = "",
1256
+ dataAttributes,
1164
1257
  direction,
1165
1258
  forwardedRef,
1166
1259
  id: idFromProps,
@@ -1285,6 +1378,10 @@ function PanelGroupWithForwardedRef({
1285
1378
  unsafeLayout = loadPanelLayout(autoSaveId, panelDataArray, storage);
1286
1379
  }
1287
1380
  const groupSizePixels = calculateAvailablePanelSizeInPixels(groupId);
1381
+ if (groupSizePixels <= 0) {
1382
+ // Wait until the group has rendered a non-zero size before computing layout.
1383
+ return;
1384
+ }
1288
1385
  if (unsafeLayout == null) {
1289
1386
  unsafeLayout = calculateUnsafeDefaultLayout({
1290
1387
  groupSizePixels,
@@ -1528,7 +1625,7 @@ function PanelGroupWithForwardedRef({
1528
1625
  } = committedValuesRef.current;
1529
1626
  const {
1530
1627
  initialLayout
1531
- } = dragState ?? {};
1628
+ } = dragState !== null && dragState !== void 0 ? dragState : {};
1532
1629
  const pivotIndices = determinePivotIndices(groupId, dragHandleId);
1533
1630
  let delta = calculateDeltaPercentage(event, groupId, dragHandleId, direction, dragState, {
1534
1631
  percentage: keyboardResizeByPercentage,
@@ -1548,7 +1645,7 @@ function PanelGroupWithForwardedRef({
1548
1645
  const nextLayout = adjustLayoutByDelta({
1549
1646
  delta,
1550
1647
  groupSizePixels,
1551
- layout: initialLayout ?? prevLayout,
1648
+ layout: initialLayout !== null && initialLayout !== void 0 ? initialLayout : prevLayout,
1552
1649
  panelConstraints,
1553
1650
  pivotIndices,
1554
1651
  trigger: isKeyDown(event) ? "keyboard" : "mouse-or-touch"
@@ -1689,11 +1786,11 @@ function PanelGroupWithForwardedRef({
1689
1786
  ...style,
1690
1787
  ...styleFromProps
1691
1788
  },
1789
+ ...dataAttributes,
1692
1790
  // CSS selectors
1693
1791
  "data-panel-group": "",
1694
- // e2e test attributes
1695
- "data-panel-group-direction": undefined,
1696
- "data-panel-group-id": undefined
1792
+ "data-panel-group-direction": direction,
1793
+ "data-panel-group-id": groupId
1697
1794
  }));
1698
1795
  }
1699
1796
  const PanelGroup = forwardRef((props, ref) => createElement(PanelGroupWithForwardedRef, {
@@ -1777,6 +1874,7 @@ function useWindowSplitterResizeHandlerBehavior({
1777
1874
  function PanelResizeHandle({
1778
1875
  children = null,
1779
1876
  className: classNameFromProps = "",
1877
+ dataAttributes,
1780
1878
  disabled = false,
1781
1879
  id: idFromProps = null,
1782
1880
  onDragging,
@@ -1805,7 +1903,7 @@ function PanelResizeHandle({
1805
1903
  stopDragging
1806
1904
  } = panelGroupContext;
1807
1905
  const resizeHandleId = useUniqueId(idFromProps);
1808
- const isDragging = dragState?.dragHandleId === resizeHandleId;
1906
+ const isDragging = (dragState === null || dragState === void 0 ? void 0 : dragState.dragHandleId) === resizeHandleId;
1809
1907
  const [isFocused, setIsFocused] = useState(false);
1810
1908
  const [resizeHandler, setResizeHandler] = useState(null);
1811
1909
  const stopDraggingAndBlur = useCallback(() => {
@@ -1869,13 +1967,6 @@ function PanelResizeHandle({
1869
1967
  return createElement(Type, {
1870
1968
  children,
1871
1969
  className: classNameFromProps,
1872
- // CSS selectors
1873
- "data-resize-handle": "",
1874
- "data-resize-handle-active": isDragging ? "pointer" : isFocused ? "keyboard" : undefined,
1875
- "data-panel-group-direction": direction,
1876
- "data-panel-group-id": groupId,
1877
- "data-panel-resize-handle-enabled": !disabled,
1878
- "data-panel-resize-handle-id": resizeHandleId,
1879
1970
  onBlur: () => setIsFocused(false),
1880
1971
  onFocus: () => setIsFocused(true),
1881
1972
  onMouseDown: event => {
@@ -1905,7 +1996,15 @@ function PanelResizeHandle({
1905
1996
  ...style,
1906
1997
  ...styleFromProps
1907
1998
  },
1908
- tabIndex: 0
1999
+ tabIndex: 0,
2000
+ ...dataAttributes,
2001
+ // CSS selectors
2002
+ "data-panel-group-direction": direction,
2003
+ "data-panel-group-id": groupId,
2004
+ "data-resize-handle": "",
2005
+ "data-resize-handle-active": isDragging ? "pointer" : isFocused ? "keyboard" : undefined,
2006
+ "data-panel-resize-handle-enabled": !disabled,
2007
+ "data-panel-resize-handle-id": resizeHandleId
1909
2008
  });
1910
2009
  }
1911
2010
  PanelResizeHandle.displayName = "PanelResizeHandle";