@primer/react 38.4.0 → 38.4.1-rc.0e4121b97

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.

Potentially problematic release.


This version of @primer/react might be problematic. Click here for more details.

@@ -5,13 +5,63 @@ import { useId } from '../hooks/useId.js';
5
5
  import { useRefObjectAsForwardedRef } from '../hooks/useRefObjectAsForwardedRef.js';
6
6
  import { isResponsiveValue } from '../hooks/useResponsiveValue.js';
7
7
  import { useSlots } from '../hooks/useSlots.js';
8
- import { canUseDOM } from '../utils/environment.js';
9
8
  import { useOverflow } from '../hooks/useOverflow.js';
10
9
  import { warning } from '../utils/warning.js';
11
10
  import { getResponsiveAttributes } from '../internal/utils/getResponsiveAttributes.js';
12
11
  import classes from './PageLayout.module.css.js';
12
+ import useIsomorphicLayoutEffect from '../utils/useIsomorphicLayoutEffect.js';
13
13
  import { jsxs, jsx } from 'react/jsx-runtime';
14
14
 
15
+ let viewportWidthListeners;
16
+ let viewportWidthObserver;
17
+ function subscribeToViewportWidth(callback) {
18
+ if (!viewportWidthListeners) {
19
+ viewportWidthListeners = new Set();
20
+ viewportWidthObserver = new ResizeObserver(() => {
21
+ if (viewportWidthListeners) {
22
+ for (const listener of viewportWidthListeners) {
23
+ listener();
24
+ }
25
+ }
26
+ });
27
+ viewportWidthObserver.observe(document.documentElement);
28
+ }
29
+ viewportWidthListeners.add(callback);
30
+ return () => {
31
+ var _viewportWidthListene, _viewportWidthListene2;
32
+ (_viewportWidthListene = viewportWidthListeners) === null || _viewportWidthListene === void 0 ? void 0 : _viewportWidthListene.delete(callback);
33
+ if (((_viewportWidthListene2 = viewportWidthListeners) === null || _viewportWidthListene2 === void 0 ? void 0 : _viewportWidthListene2.size) === 0) {
34
+ var _viewportWidthObserve;
35
+ (_viewportWidthObserve = viewportWidthObserver) === null || _viewportWidthObserve === void 0 ? void 0 : _viewportWidthObserve.disconnect();
36
+ viewportWidthObserver = undefined;
37
+ viewportWidthListeners = undefined;
38
+ }
39
+ };
40
+ }
41
+ function getViewportWidth() {
42
+ return window.innerWidth;
43
+ }
44
+ function getServerViewportWidth() {
45
+ return 0;
46
+ }
47
+
48
+ /**
49
+ * Custom hook that subscribes to viewport width changes using a shared ResizeObserver
50
+ */
51
+ function useViewportWidth() {
52
+ return React.useSyncExternalStore(subscribeToViewportWidth, getViewportWidth, getServerViewportWidth);
53
+ }
54
+
55
+ /**
56
+ * Gets the --pane-max-width-diff CSS variable value from a pane element.
57
+ * This value is set by CSS media queries and controls the max pane width constraint.
58
+ * Falls back to 511 (the CSS default) if the value cannot be read.
59
+ */
60
+ function getPaneMaxWidthDiff(paneElement) {
61
+ if (!paneElement) return 511;
62
+ const value = parseInt(getComputedStyle(paneElement).getPropertyValue('--pane-max-width-diff'), 10);
63
+ return value > 0 ? value : 511;
64
+ }
15
65
  const PageLayoutContext = /*#__PURE__*/React.createContext({
16
66
  padding: 'normal',
17
67
  rowGap: 'normal',
@@ -224,12 +274,27 @@ const HorizontalDivider = t0 => {
224
274
  }
225
275
  return t8;
226
276
  };
277
+ // Helper to update ARIA slider attributes via direct DOM manipulation
278
+ // This avoids re-renders when values change during drag or on viewport resize
279
+ const updateAriaValues = (handle, values) => {
280
+ if (!handle) return;
281
+ if (values.min !== undefined) handle.setAttribute('aria-valuemin', String(values.min));
282
+ if (values.max !== undefined) handle.setAttribute('aria-valuemax', String(values.max));
283
+ if (values.current !== undefined) {
284
+ handle.setAttribute('aria-valuenow', String(values.current));
285
+ handle.setAttribute('aria-valuetext', `Pane width ${values.current} pixels`);
286
+ }
287
+ };
288
+ const DATA_DRAGGING_ATTR = 'data-dragging';
289
+ const isDragging = handle => {
290
+ return (handle === null || handle === void 0 ? void 0 : handle.getAttribute(DATA_DRAGGING_ATTR)) === 'true';
291
+ };
227
292
  const VerticalDivider = t0 => {
228
- const $ = c(40);
293
+ const $ = c(32);
229
294
  const {
230
295
  variant: t1,
231
296
  draggable: t2,
232
- onDragStart,
297
+ handleRef,
233
298
  onDrag,
234
299
  onDragEnd,
235
300
  onDoubleClick,
@@ -239,234 +304,175 @@ const VerticalDivider = t0 => {
239
304
  } = t0;
240
305
  const variant = t1 === undefined ? "none" : t1;
241
306
  const draggable = t2 === undefined ? false : t2;
242
- const [isDragging, setIsDragging] = React.useState(false);
243
- const [isKeyboardDrag, setIsKeyboardDrag] = React.useState(false);
244
307
  const stableOnDrag = React.useRef(onDrag);
245
308
  const stableOnDragEnd = React.useRef(onDragEnd);
246
- const {
247
- paneRef
248
- } = React.useContext(PageLayoutContext);
249
- const [minWidth, setMinWidth] = React.useState(0);
250
- const [maxWidth, setMaxWidth] = React.useState(0);
251
- const [currentWidth, setCurrentWidth] = React.useState(0);
252
309
  let t3;
253
- if ($[0] !== paneRef) {
310
+ if ($[0] !== onDrag || $[1] !== onDragEnd) {
254
311
  t3 = () => {
255
- if (paneRef.current !== null) {
256
- const paneStyles = getComputedStyle(paneRef.current);
257
- const maxPaneWidthDiffPixels = paneStyles.getPropertyValue("--pane-max-width-diff");
258
- const minWidthPixels = paneStyles.getPropertyValue("--pane-min-width");
259
- const paneWidth = paneRef.current.getBoundingClientRect().width;
260
- const maxPaneWidthDiff = Number(maxPaneWidthDiffPixels.split("px")[0]);
261
- const minPaneWidth = Number(minWidthPixels.split("px")[0]);
262
- const viewportWidth = window.innerWidth;
263
- const maxPaneWidth = viewportWidth > maxPaneWidthDiff ? viewportWidth - maxPaneWidthDiff : viewportWidth;
264
- setMinWidth(minPaneWidth);
265
- setMaxWidth(maxPaneWidth);
266
- setCurrentWidth(paneWidth || 0);
267
- }
312
+ stableOnDrag.current = onDrag;
313
+ stableOnDragEnd.current = onDragEnd;
268
314
  };
269
- $[0] = paneRef;
270
- $[1] = t3;
315
+ $[0] = onDrag;
316
+ $[1] = onDragEnd;
317
+ $[2] = t3;
271
318
  } else {
272
- t3 = $[1];
319
+ t3 = $[2];
273
320
  }
321
+ React.useEffect(t3);
322
+ const {
323
+ paneRef
324
+ } = React.useContext(PageLayoutContext);
325
+ const handlePointerDown = _temp;
274
326
  let t4;
275
- if ($[2] !== isDragging || $[3] !== isKeyboardDrag || $[4] !== paneRef) {
276
- t4 = [paneRef, isKeyboardDrag, isDragging];
277
- $[2] = isDragging;
278
- $[3] = isKeyboardDrag;
279
- $[4] = paneRef;
280
- $[5] = t4;
327
+ if ($[3] !== handleRef) {
328
+ t4 = event_0 => {
329
+ if (!isDragging(handleRef.current)) {
330
+ return;
331
+ }
332
+ event_0.preventDefault();
333
+ if (event_0.movementX !== 0) {
334
+ stableOnDrag.current(event_0.movementX, false);
335
+ }
336
+ };
337
+ $[3] = handleRef;
338
+ $[4] = t4;
281
339
  } else {
282
- t4 = $[5];
340
+ t4 = $[4];
283
341
  }
284
- React.useEffect(t3, t4);
342
+ const handlePointerMove = t4;
285
343
  let t5;
344
+ if ($[5] !== handleRef) {
345
+ t5 = event_1 => {
346
+ if (!isDragging(handleRef.current)) {
347
+ return;
348
+ }
349
+ event_1.preventDefault();
350
+ };
351
+ $[5] = handleRef;
352
+ $[6] = t5;
353
+ } else {
354
+ t5 = $[6];
355
+ }
356
+ const handlePointerUp = t5;
286
357
  let t6;
287
- if ($[6] !== onDrag) {
288
- t5 = () => {
289
- stableOnDrag.current = onDrag;
358
+ if ($[7] !== handleRef) {
359
+ t6 = event_2 => {
360
+ if (!isDragging(handleRef.current)) {
361
+ return;
362
+ }
363
+ const target_0 = event_2.currentTarget;
364
+ target_0.removeAttribute(DATA_DRAGGING_ATTR);
365
+ stableOnDragEnd.current();
290
366
  };
291
- t6 = [onDrag];
292
- $[6] = onDrag;
293
- $[7] = t5;
367
+ $[7] = handleRef;
294
368
  $[8] = t6;
295
369
  } else {
296
- t5 = $[7];
297
370
  t6 = $[8];
298
371
  }
299
- React.useEffect(t5, t6);
372
+ const handleLostPointerCapture = t6;
300
373
  let t7;
301
- let t8;
302
- if ($[9] !== onDragEnd) {
303
- t7 = () => {
304
- stableOnDragEnd.current = onDragEnd;
374
+ if ($[9] !== paneRef) {
375
+ t7 = event_3 => {
376
+ if (event_3.key === "ArrowLeft" || event_3.key === "ArrowRight" || event_3.key === "ArrowUp" || event_3.key === "ArrowDown") {
377
+ event_3.preventDefault();
378
+ if (!paneRef.current) {
379
+ return;
380
+ }
381
+ const delta = event_3.key === "ArrowLeft" || event_3.key === "ArrowDown" ? -3 : 3;
382
+ event_3.currentTarget.setAttribute(DATA_DRAGGING_ATTR, "true");
383
+ stableOnDrag.current(delta, true);
384
+ }
305
385
  };
306
- t8 = [onDragEnd];
307
- $[9] = onDragEnd;
386
+ $[9] = paneRef;
308
387
  $[10] = t7;
309
- $[11] = t8;
310
388
  } else {
311
389
  t7 = $[10];
312
- t8 = $[11];
313
390
  }
314
- React.useEffect(t7, t8);
315
- let t10;
316
- let t9;
317
- if ($[12] !== currentWidth || $[13] !== isDragging || $[14] !== isKeyboardDrag || $[15] !== maxWidth || $[16] !== minWidth) {
318
- t9 = () => {
319
- const handleDrag = function handleDrag(event) {
320
- var _stableOnDrag$current;
321
- (_stableOnDrag$current = stableOnDrag.current) === null || _stableOnDrag$current === void 0 ? void 0 : _stableOnDrag$current.call(stableOnDrag, event.movementX, false);
322
- event.preventDefault();
323
- };
324
- const handleDragEnd = function handleDragEnd(event_0) {
325
- var _stableOnDragEnd$curr;
326
- setIsDragging(false);
327
- (_stableOnDragEnd$curr = stableOnDragEnd.current) === null || _stableOnDragEnd$curr === void 0 ? void 0 : _stableOnDragEnd$curr.call(stableOnDragEnd);
328
- event_0.preventDefault();
329
- };
330
- const handleKeyDrag = function handleKeyDrag(event_1) {
331
- var _stableOnDrag$current2;
332
- let delta;
333
- if ((event_1.key === "ArrowLeft" || event_1.key === "ArrowDown") && currentWidth > minWidth) {
334
- delta = -3;
335
- } else {
336
- if ((event_1.key === "ArrowRight" || event_1.key === "ArrowUp") && currentWidth < maxWidth) {
337
- delta = 3;
338
- } else {
339
- return;
340
- }
341
- }
342
- setCurrentWidth(currentWidth + delta);
343
- (_stableOnDrag$current2 = stableOnDrag.current) === null || _stableOnDrag$current2 === void 0 ? void 0 : _stableOnDrag$current2.call(stableOnDrag, delta, true);
344
- event_1.preventDefault();
345
- };
346
- const handleKeyDragEnd = function handleKeyDragEnd(event_2) {
347
- var _stableOnDragEnd$curr2;
348
- setIsKeyboardDrag(false);
349
- (_stableOnDragEnd$curr2 = stableOnDragEnd.current) === null || _stableOnDragEnd$curr2 === void 0 ? void 0 : _stableOnDragEnd$curr2.call(stableOnDragEnd);
350
- event_2.preventDefault();
351
- };
352
- if (isDragging || isKeyboardDrag) {
353
- window.addEventListener("mousemove", handleDrag);
354
- window.addEventListener("keydown", handleKeyDrag);
355
- window.addEventListener("mouseup", handleDragEnd);
356
- window.addEventListener("keyup", handleKeyDragEnd);
357
- const body = document.body;
358
- body === null || body === void 0 ? void 0 : body.setAttribute("data-page-layout-dragging", "true");
359
- } else {
360
- window.removeEventListener("mousemove", handleDrag);
361
- window.removeEventListener("mouseup", handleDragEnd);
362
- window.removeEventListener("keydown", handleKeyDrag);
363
- window.removeEventListener("keyup", handleKeyDragEnd);
364
- const body_0 = document.body;
365
- body_0 === null || body_0 === void 0 ? void 0 : body_0.removeAttribute("data-page-layout-dragging");
391
+ const handleKeyDown = t7;
392
+ let t8;
393
+ if ($[11] === Symbol.for("react.memo_cache_sentinel")) {
394
+ t8 = event_4 => {
395
+ if (event_4.key === "ArrowLeft" || event_4.key === "ArrowRight" || event_4.key === "ArrowUp" || event_4.key === "ArrowDown") {
396
+ event_4.preventDefault();
397
+ event_4.currentTarget.removeAttribute(DATA_DRAGGING_ATTR);
398
+ stableOnDragEnd.current();
366
399
  }
367
- return () => {
368
- window.removeEventListener("mousemove", handleDrag);
369
- window.removeEventListener("mouseup", handleDragEnd);
370
- window.removeEventListener("keydown", handleKeyDrag);
371
- window.removeEventListener("keyup", handleKeyDragEnd);
372
- const body_1 = document.body;
373
- body_1 === null || body_1 === void 0 ? void 0 : body_1.removeAttribute("data-page-layout-dragging");
374
- };
375
400
  };
376
- t10 = [isDragging, isKeyboardDrag, currentWidth, minWidth, maxWidth];
377
- $[12] = currentWidth;
378
- $[13] = isDragging;
379
- $[14] = isKeyboardDrag;
380
- $[15] = maxWidth;
381
- $[16] = minWidth;
382
- $[17] = t10;
383
- $[18] = t9;
401
+ $[11] = t8;
384
402
  } else {
385
- t10 = $[17];
386
- t9 = $[18];
403
+ t8 = $[11];
387
404
  }
388
- React.useEffect(t9, t10);
389
- let t11;
390
- if ($[19] !== className) {
391
- t11 = clsx(classes.VerticalDivider, className);
392
- $[19] = className;
393
- $[20] = t11;
405
+ const handleKeyUp = t8;
406
+ let t9;
407
+ if ($[12] !== className) {
408
+ t9 = clsx(classes.VerticalDivider, className);
409
+ $[12] = className;
410
+ $[13] = t9;
394
411
  } else {
395
- t11 = $[20];
412
+ t9 = $[13];
396
413
  }
397
- let t12;
398
- if ($[21] !== variant) {
399
- t12 = getResponsiveAttributes("variant", variant);
400
- $[21] = variant;
401
- $[22] = t12;
414
+ let t10;
415
+ if ($[14] !== variant) {
416
+ t10 = getResponsiveAttributes("variant", variant);
417
+ $[14] = variant;
418
+ $[15] = t10;
402
419
  } else {
403
- t12 = $[22];
420
+ t10 = $[15];
404
421
  }
405
- let t13;
406
- if ($[23] !== position) {
407
- t13 = getResponsiveAttributes("position", position);
408
- $[23] = position;
409
- $[24] = t13;
422
+ let t11;
423
+ if ($[16] !== position) {
424
+ t11 = getResponsiveAttributes("position", position);
425
+ $[16] = position;
426
+ $[17] = t11;
410
427
  } else {
411
- t13 = $[24];
428
+ t11 = $[17];
412
429
  }
413
- let t14;
414
- if ($[25] !== currentWidth || $[26] !== draggable || $[27] !== isDragging || $[28] !== isKeyboardDrag || $[29] !== maxWidth || $[30] !== minWidth || $[31] !== onDoubleClick || $[32] !== onDragStart) {
415
- t14 = draggable ? /*#__PURE__*/jsx("div", {
430
+ let t12;
431
+ if ($[18] !== draggable || $[19] !== handleKeyDown || $[20] !== handleLostPointerCapture || $[21] !== handlePointerMove || $[22] !== handlePointerUp || $[23] !== handleRef || $[24] !== onDoubleClick) {
432
+ t12 = draggable ? /*#__PURE__*/jsx("div", {
433
+ ref: handleRef,
416
434
  className: classes.DraggableHandle,
417
- "data-dragging": isDragging || isKeyboardDrag,
418
435
  role: "slider",
419
436
  "aria-label": "Draggable pane splitter",
420
- "aria-valuemin": minWidth,
421
- "aria-valuemax": maxWidth,
422
- "aria-valuenow": currentWidth,
423
- "aria-valuetext": `Pane width ${currentWidth} pixels`,
424
437
  tabIndex: 0,
425
- onMouseDown: event_3 => {
426
- if (event_3.button === 0) {
427
- setIsDragging(true);
428
- onDragStart === null || onDragStart === void 0 ? void 0 : onDragStart();
429
- }
430
- },
431
- onKeyDown: event_4 => {
432
- if (event_4.key === "ArrowLeft" || event_4.key === "ArrowRight" || event_4.key === "ArrowUp" || event_4.key === "ArrowDown") {
433
- setIsKeyboardDrag(true);
434
- onDragStart === null || onDragStart === void 0 ? void 0 : onDragStart();
435
- }
436
- },
438
+ onPointerDown: handlePointerDown,
439
+ onPointerMove: handlePointerMove,
440
+ onPointerUp: handlePointerUp,
441
+ onLostPointerCapture: handleLostPointerCapture,
442
+ onKeyDown: handleKeyDown,
443
+ onKeyUp: handleKeyUp,
437
444
  onDoubleClick: onDoubleClick
438
445
  }) : null;
439
- $[25] = currentWidth;
440
- $[26] = draggable;
441
- $[27] = isDragging;
442
- $[28] = isKeyboardDrag;
443
- $[29] = maxWidth;
444
- $[30] = minWidth;
445
- $[31] = onDoubleClick;
446
- $[32] = onDragStart;
447
- $[33] = t14;
446
+ $[18] = draggable;
447
+ $[19] = handleKeyDown;
448
+ $[20] = handleLostPointerCapture;
449
+ $[21] = handlePointerMove;
450
+ $[22] = handlePointerUp;
451
+ $[23] = handleRef;
452
+ $[24] = onDoubleClick;
453
+ $[25] = t12;
448
454
  } else {
449
- t14 = $[33];
455
+ t12 = $[25];
450
456
  }
451
- let t15;
452
- if ($[34] !== style || $[35] !== t11 || $[36] !== t12 || $[37] !== t13 || $[38] !== t14) {
453
- t15 = /*#__PURE__*/jsx("div", {
454
- className: t11,
455
- ...t12,
456
- ...t13,
457
+ let t13;
458
+ if ($[26] !== style || $[27] !== t10 || $[28] !== t11 || $[29] !== t12 || $[30] !== t9) {
459
+ t13 = /*#__PURE__*/jsx("div", {
460
+ className: t9,
461
+ ...t10,
462
+ ...t11,
457
463
  style: style,
458
- children: t14
464
+ children: t12
459
465
  });
460
- $[34] = style;
461
- $[35] = t11;
462
- $[36] = t12;
463
- $[37] = t13;
464
- $[38] = t14;
465
- $[39] = t15;
466
+ $[26] = style;
467
+ $[27] = t10;
468
+ $[28] = t11;
469
+ $[29] = t12;
470
+ $[30] = t9;
471
+ $[31] = t13;
466
472
  } else {
467
- t15 = $[39];
473
+ t13 = $[31];
468
474
  }
469
- return t15;
475
+ return t13;
470
476
  };
471
477
 
472
478
  // ----------------------------------------------------------------------------
@@ -705,6 +711,14 @@ const isCustomWidthOptions = width => {
705
711
  const isPaneWidth = width => {
706
712
  return ['small', 'medium', 'large'].includes(width);
707
713
  };
714
+ const getDefaultPaneWidth = w => {
715
+ if (isPaneWidth(w)) {
716
+ return defaultPaneWidth[w];
717
+ } else if (isCustomWidthOptions(w)) {
718
+ return parseInt(w.default, 10);
719
+ }
720
+ return 0;
721
+ };
708
722
  const defaultPaneWidth = {
709
723
  small: 256,
710
724
  medium: 296,
@@ -714,422 +728,241 @@ const overflowProps = {
714
728
  tabIndex: 0,
715
729
  role: 'region'
716
730
  };
717
- const Pane = /*#__PURE__*/React.forwardRef((t0, forwardRef) => {
718
- const $ = c(92);
719
- const {
720
- "aria-label": label,
721
- "aria-labelledby": labelledBy,
722
- position: t1,
723
- positionWhenNarrow: t2,
724
- width: t3,
725
- minWidth: t4,
726
- padding: t5,
727
- resizable: t6,
728
- widthStorageKey: t7,
729
- divider: t8,
730
- dividerWhenNarrow: t9,
731
- sticky: t10,
732
- offsetHeader: t11,
733
- hidden: t12,
734
- children,
735
- id,
736
- className,
737
- style
738
- } = t0;
739
- const responsivePosition = t1 === undefined ? "end" : t1;
740
- const positionWhenNarrow = t2 === undefined ? "inherit" : t2;
741
- const width = t3 === undefined ? "medium" : t3;
742
- const minWidth = t4 === undefined ? 256 : t4;
743
- const padding = t5 === undefined ? "none" : t5;
744
- const resizable = t6 === undefined ? false : t6;
745
- const widthStorageKey = t7 === undefined ? "paneWidth" : t7;
746
- const responsiveDivider = t8 === undefined ? "none" : t8;
747
- const dividerWhenNarrow = t9 === undefined ? "inherit" : t9;
748
- const sticky = t10 === undefined ? false : t10;
749
- const offsetHeader = t11 === undefined ? 0 : t11;
750
- const responsiveHidden = t12 === undefined ? false : t12;
751
- let t13;
752
- if ($[0] !== positionWhenNarrow || $[1] !== responsivePosition) {
753
- t13 = !isResponsiveValue(responsivePosition) && positionWhenNarrow !== "inherit" ? {
754
- regular: responsivePosition,
755
- narrow: positionWhenNarrow
756
- } : responsivePosition;
757
- $[0] = positionWhenNarrow;
758
- $[1] = responsivePosition;
759
- $[2] = t13;
760
- } else {
761
- t13 = $[2];
762
- }
763
- const positionProp = t13;
764
- let t14;
765
- if ($[3] !== dividerWhenNarrow || $[4] !== responsiveDivider) {
766
- t14 = !isResponsiveValue(responsiveDivider) && dividerWhenNarrow !== "inherit" ? {
767
- regular: responsiveDivider,
768
- narrow: dividerWhenNarrow
769
- } : responsiveDivider;
770
- $[3] = dividerWhenNarrow;
771
- $[4] = responsiveDivider;
772
- $[5] = t14;
773
- } else {
774
- t14 = $[5];
775
- }
776
- const dividerProp = t14;
777
- let t15;
778
- if ($[6] !== positionProp) {
779
- t15 = isResponsiveValue(positionProp) ? "end" : positionProp;
780
- $[6] = positionProp;
781
- $[7] = t15;
782
- } else {
783
- t15 = $[7];
784
- }
785
- const position = t15;
786
- let t16;
787
- if ($[8] !== dividerProp) {
788
- t16 = isResponsiveValue(dividerProp) ? "none" : dividerProp;
789
- $[8] = dividerProp;
790
- $[9] = t16;
791
- } else {
792
- t16 = $[9];
793
- }
794
- const dividerVariant = t16;
731
+ const Pane = /*#__PURE__*/React.forwardRef(({
732
+ 'aria-label': label,
733
+ 'aria-labelledby': labelledBy,
734
+ position: responsivePosition = 'end',
735
+ positionWhenNarrow = 'inherit',
736
+ width = 'medium',
737
+ minWidth = 256,
738
+ padding = 'none',
739
+ resizable = false,
740
+ widthStorageKey = 'paneWidth',
741
+ divider: responsiveDivider = 'none',
742
+ dividerWhenNarrow = 'inherit',
743
+ sticky = false,
744
+ offsetHeader = 0,
745
+ hidden: responsiveHidden = false,
746
+ children,
747
+ id,
748
+ className,
749
+ style
750
+ }, forwardRef) => {
751
+ // Combine position and positionWhenNarrow for backwards compatibility
752
+ const positionProp = !isResponsiveValue(responsivePosition) && positionWhenNarrow !== 'inherit' ? {
753
+ regular: responsivePosition,
754
+ narrow: positionWhenNarrow
755
+ } : responsivePosition;
756
+
757
+ // Combine divider and dividerWhenNarrow for backwards compatibility
758
+ const dividerProp = !isResponsiveValue(responsiveDivider) && dividerWhenNarrow !== 'inherit' ? {
759
+ regular: responsiveDivider,
760
+ narrow: dividerWhenNarrow
761
+ } : responsiveDivider;
762
+
763
+ // For components that need responsive values in JavaScript logic, we'll use a fallback value
764
+ // The actual responsive behavior will be handled by CSS through data attributes
765
+ const position = isResponsiveValue(positionProp) ? 'end' : positionProp;
766
+ const dividerVariant = isResponsiveValue(dividerProp) ? 'none' : dividerProp;
795
767
  const {
796
768
  rowGap,
797
769
  columnGap,
798
770
  paneRef
799
771
  } = React.useContext(PageLayoutContext);
800
- const getDefaultPaneWidth = _temp;
801
- let t17;
802
- if ($[10] !== width || $[11] !== widthStorageKey) {
803
- t17 = () => {
804
- if (!canUseDOM) {
805
- return getDefaultPaneWidth(width);
806
- }
807
- let storedWidth;
808
- try {
809
- storedWidth = localStorage.getItem(widthStorageKey);
810
- } catch (t18) {
811
- storedWidth = null;
812
- }
813
- return storedWidth && !isNaN(Number(storedWidth)) ? Number(storedWidth) : getDefaultPaneWidth(width);
814
- };
815
- $[10] = width;
816
- $[11] = widthStorageKey;
817
- $[12] = t17;
818
- } else {
819
- t17 = $[12];
820
- }
821
- const [paneWidth, setPaneWidth] = React.useState(t17);
822
- let t18;
823
- if ($[13] !== widthStorageKey) {
824
- t18 = width_1 => {
825
- setPaneWidth(width_1);
826
- try {
827
- localStorage.setItem(widthStorageKey, width_1.toString());
828
- } catch (t19) {
772
+
773
+ // Initial pane width for the first render - only used to set the initial CSS variable.
774
+ // After mount, all updates go directly to the DOM via style.setProperty() to avoid re-renders.
775
+ const defaultWidth = getDefaultPaneWidth(width);
776
+
777
+ // Track current width during drag - initialized lazily in layout effect
778
+ const currentWidthRef = React.useRef(defaultWidth);
779
+
780
+ // Track whether we've initialized the width from localStorage
781
+ const initializedRef = React.useRef(false);
782
+ useIsomorphicLayoutEffect(() => {
783
+ var _paneRef$current2;
784
+ // Only initialize once on mount - subsequent updates come from drag operations
785
+ if (initializedRef.current || !resizable) return;
786
+ initializedRef.current = true;
787
+ // Before paint, check localStorage for a stored width
788
+ try {
789
+ const value = localStorage.getItem(widthStorageKey);
790
+ if (value !== null && !isNaN(Number(value))) {
791
+ var _paneRef$current;
792
+ const num = Number(value);
793
+ currentWidthRef.current = num;
794
+ (_paneRef$current = paneRef.current) === null || _paneRef$current === void 0 ? void 0 : _paneRef$current.style.setProperty('--pane-width', `${num}px`);
795
+ return;
829
796
  }
830
- };
831
- $[13] = widthStorageKey;
832
- $[14] = t18;
833
- } else {
834
- t18 = $[14];
835
- }
836
- const updatePaneWidth = t18;
797
+ } catch {
798
+ // localStorage unavailable - set default via DOM
799
+ }
800
+ (_paneRef$current2 = paneRef.current) === null || _paneRef$current2 === void 0 ? void 0 : _paneRef$current2.style.setProperty('--pane-width', `${defaultWidth}px`);
801
+ }, [widthStorageKey, paneRef, resizable, defaultWidth]);
802
+
803
+ // Subscribe to viewport width changes for responsive max constraint calculation
804
+ const viewportWidth = useViewportWidth();
805
+
806
+ // Calculate min width constraint from width configuration
807
+ const minPaneWidth = isCustomWidthOptions(width) ? parseInt(width.min, 10) : minWidth;
808
+
809
+ // Cache max width constraint - updated when viewport changes (which triggers CSS breakpoint changes)
810
+ // This avoids calling getComputedStyle() on every drag frame
811
+ const maxPaneWidthRef = React.useRef(minPaneWidth);
812
+ React.useEffect(() => {
813
+ if (isCustomWidthOptions(width)) {
814
+ maxPaneWidthRef.current = parseInt(width.max, 10);
815
+ } else {
816
+ const maxWidthDiff = getPaneMaxWidthDiff(paneRef.current);
817
+ maxPaneWidthRef.current = viewportWidth > 0 ? Math.max(minPaneWidth, viewportWidth - maxWidthDiff) : minPaneWidth;
818
+ }
819
+ }, [width, minPaneWidth, viewportWidth, paneRef]);
820
+
821
+ // Ref to the drag handle for updating ARIA attributes
822
+ const handleRef = React.useRef(null);
823
+
824
+ // Update ARIA attributes on mount and when viewport/constraints change
825
+ useIsomorphicLayoutEffect(() => {
826
+ updateAriaValues(handleRef.current, {
827
+ min: minPaneWidth,
828
+ max: maxPaneWidthRef.current,
829
+ current: currentWidthRef.current
830
+ });
831
+ }, [minPaneWidth, viewportWidth]);
837
832
  useRefObjectAsForwardedRef(forwardRef, paneRef);
838
833
  const hasOverflow = useOverflow(paneRef);
839
834
  const paneId = useId(id);
840
- let labelProp;
841
- if ($[15] !== hasOverflow || $[16] !== label || $[17] !== labelledBy) {
842
- labelProp = {};
843
- if (hasOverflow) {
844
- process.env.NODE_ENV !== "production" ? warning(label === undefined && labelledBy === undefined, "The <PageLayout.Pane> has overflow and `aria-label` or `aria-labelledby` has not been set. Please provide `aria-label` or `aria-labelledby` to <PageLayout.Pane> in order to label this region.") : void 0;
845
- if (labelledBy) {
846
- labelProp["aria-labelledby"] = labelledBy;
847
- } else {
848
- if (label) {
849
- labelProp["aria-label"] = label;
850
- }
851
- }
835
+ const labelProp = {};
836
+ if (hasOverflow) {
837
+ process.env.NODE_ENV !== "production" ? warning(label === undefined && labelledBy === undefined, 'The <PageLayout.Pane> has overflow and `aria-label` or `aria-labelledby` has not been set. ' + 'Please provide `aria-label` or `aria-labelledby` to <PageLayout.Pane> in order to label this ' + 'region.') : void 0;
838
+ if (labelledBy) {
839
+ labelProp['aria-labelledby'] = labelledBy;
840
+ } else if (label) {
841
+ labelProp['aria-label'] = label;
852
842
  }
853
- $[15] = hasOverflow;
854
- $[16] = label;
855
- $[17] = labelledBy;
856
- $[18] = labelProp;
857
- } else {
858
- labelProp = $[18];
859
- }
860
- let t19;
861
- if ($[19] !== className) {
862
- t19 = clsx(classes.PaneWrapper, className);
863
- $[19] = className;
864
- $[20] = t19;
865
- } else {
866
- t19 = $[20];
867
843
  }
868
- const t20 = typeof offsetHeader === "number" ? `${offsetHeader}px` : offsetHeader;
869
- const t21 = `var(--spacing-${rowGap})`;
870
- const t22 = `var(--spacing-${columnGap})`;
871
- let t23;
872
- if ($[21] !== style || $[22] !== t20 || $[23] !== t21 || $[24] !== t22) {
873
- t23 = {
874
- "--offset-header": t20,
875
- "--spacing-row": t21,
876
- "--spacing-column": t22,
844
+ const setWidthInLocalStorage = value_0 => {
845
+ try {
846
+ localStorage.setItem(widthStorageKey, value_0.toString());
847
+ } catch {
848
+ // Ignore write errors
849
+ }
850
+ };
851
+ return /*#__PURE__*/jsxs("div", {
852
+ className: clsx(classes.PaneWrapper, className),
853
+ style: {
854
+ '--offset-header': typeof offsetHeader === 'number' ? `${offsetHeader}px` : offsetHeader,
855
+ '--spacing-row': `var(--spacing-${rowGap})`,
856
+ '--spacing-column': `var(--spacing-${columnGap})`,
877
857
  ...style
878
- };
879
- $[21] = style;
880
- $[22] = t20;
881
- $[23] = t21;
882
- $[24] = t22;
883
- $[25] = t23;
884
- } else {
885
- t23 = $[25];
886
- }
887
- const t24 = t23;
888
- let t25;
889
- if ($[26] !== responsiveHidden) {
890
- t25 = getResponsiveAttributes("is-hidden", responsiveHidden);
891
- $[26] = responsiveHidden;
892
- $[27] = t25;
893
- } else {
894
- t25 = $[27];
895
- }
896
- let t26;
897
- if ($[28] !== positionProp) {
898
- t26 = getResponsiveAttributes("position", positionProp);
899
- $[28] = positionProp;
900
- $[29] = t26;
901
- } else {
902
- t26 = $[29];
903
- }
904
- const t27 = sticky || undefined;
905
- let t28;
906
- if ($[30] !== dividerProp || $[31] !== dividerVariant) {
907
- t28 = isResponsiveValue(dividerProp) ? dividerProp : {
908
- narrow: dividerVariant,
909
- regular: "none"
910
- };
911
- $[30] = dividerProp;
912
- $[31] = dividerVariant;
913
- $[32] = t28;
914
- } else {
915
- t28 = $[32];
916
- }
917
- const t29 = `var(--spacing-${rowGap})`;
918
- let t30;
919
- if ($[33] !== t29) {
920
- t30 = {
921
- "--spacing": t29
922
- };
923
- $[33] = t29;
924
- $[34] = t30;
925
- } else {
926
- t30 = $[34];
927
- }
928
- const t31 = t30;
929
- let t32;
930
- if ($[35] !== positionProp || $[36] !== t28 || $[37] !== t31) {
931
- t32 = /*#__PURE__*/jsx(HorizontalDivider, {
932
- variant: t28,
858
+ },
859
+ ...getResponsiveAttributes('is-hidden', responsiveHidden),
860
+ ...getResponsiveAttributes('position', positionProp),
861
+ "data-sticky": sticky || undefined,
862
+ children: [/*#__PURE__*/jsx(HorizontalDivider, {
863
+ variant: isResponsiveValue(dividerProp) ? dividerProp : {
864
+ narrow: dividerVariant,
865
+ regular: 'none'
866
+ },
933
867
  className: classes.PaneHorizontalDivider,
934
- style: t31,
868
+ style: {
869
+ '--spacing': `var(--spacing-${rowGap})`
870
+ },
935
871
  position: positionProp
936
- });
937
- $[35] = positionProp;
938
- $[36] = t28;
939
- $[37] = t31;
940
- $[38] = t32;
941
- } else {
942
- t32 = $[38];
943
- }
944
- let t33;
945
- if ($[39] !== hasOverflow) {
946
- t33 = hasOverflow ? overflowProps : {};
947
- $[39] = hasOverflow;
948
- $[40] = t33;
949
- } else {
950
- t33 = $[40];
951
- }
952
- let t34;
953
- if ($[41] !== id || $[42] !== paneId) {
954
- t34 = id && {
955
- id: paneId
956
- };
957
- $[41] = id;
958
- $[42] = paneId;
959
- $[43] = t34;
960
- } else {
961
- t34 = $[43];
962
- }
963
- const t35 = resizable || undefined;
964
- const t36 = `var(--spacing-${padding})`;
965
- const t37 = isCustomWidthOptions(width) ? width.min : `${minWidth}px`;
966
- const t38 = isCustomWidthOptions(width) ? width.max : "calc(100vw - var(--pane-max-width-diff))";
967
- const t39 = isCustomWidthOptions(width) ? width.default : undefined;
968
- const t40 = `var(--pane-width-${isPaneWidth(width) ? width : "custom"})`;
969
- const t41 = `${paneWidth}px`;
970
- let t42;
971
- if ($[44] !== t36 || $[45] !== t37 || $[46] !== t38 || $[47] !== t39 || $[48] !== t40 || $[49] !== t41) {
972
- t42 = {
973
- "--spacing": t36,
974
- "--pane-min-width": t37,
975
- "--pane-max-width": t38,
976
- "--pane-width-custom": t39,
977
- "--pane-width-size": t40,
978
- "--pane-width": t41
979
- };
980
- $[44] = t36;
981
- $[45] = t37;
982
- $[46] = t38;
983
- $[47] = t39;
984
- $[48] = t40;
985
- $[49] = t41;
986
- $[50] = t42;
987
- } else {
988
- t42 = $[50];
989
- }
990
- const t43 = t42;
991
- let t44;
992
- if ($[51] !== children || $[52] !== labelProp || $[53] !== paneRef || $[54] !== t33 || $[55] !== t34 || $[56] !== t35 || $[57] !== t43) {
993
- t44 = /*#__PURE__*/jsx("div", {
872
+ }), /*#__PURE__*/jsx("div", {
994
873
  ref: paneRef,
995
- ...t33,
874
+ ...(hasOverflow ? overflowProps : {}),
996
875
  ...labelProp,
997
- ...t34,
876
+ ...(id && {
877
+ id: paneId
878
+ }),
998
879
  className: classes.Pane,
999
- "data-resizable": t35,
1000
- style: t43,
880
+ "data-resizable": resizable || undefined,
881
+ style: {
882
+ '--spacing': `var(--spacing-${padding})`,
883
+ '--pane-min-width': isCustomWidthOptions(width) ? width.min : `${minWidth}px`,
884
+ '--pane-max-width': isCustomWidthOptions(width) ? width.max : `calc(100vw - var(--pane-max-width-diff))`,
885
+ '--pane-width-custom': isCustomWidthOptions(width) ? width.default : undefined,
886
+ '--pane-width-size': `var(--pane-width-${isPaneWidth(width) ? width : 'custom'})`
887
+ // --pane-width is set via layout effect (for localStorage) and DOM manipulation (for drag).
888
+ },
1001
889
  children: children
1002
- });
1003
- $[51] = children;
1004
- $[52] = labelProp;
1005
- $[53] = paneRef;
1006
- $[54] = t33;
1007
- $[55] = t34;
1008
- $[56] = t35;
1009
- $[57] = t43;
1010
- $[58] = t44;
1011
- } else {
1012
- t44 = $[58];
1013
- }
1014
- let t45;
1015
- if ($[59] !== dividerProp || $[60] !== dividerVariant || $[61] !== resizable) {
1016
- t45 = isResponsiveValue(dividerProp) ? {
1017
- narrow: "none",
1018
- regular: resizable ? "line" : dividerProp.regular || "none",
1019
- wide: resizable ? "line" : dividerProp.wide || dividerProp.regular || "none"
1020
- } : {
1021
- narrow: "none",
1022
- regular: resizable ? "line" : dividerVariant
1023
- };
1024
- $[59] = dividerProp;
1025
- $[60] = dividerVariant;
1026
- $[61] = resizable;
1027
- $[62] = t45;
1028
- } else {
1029
- t45 = $[62];
1030
- }
1031
- let t46;
1032
- if ($[63] !== paneWidth || $[64] !== position || $[65] !== updatePaneWidth) {
1033
- t46 = (delta, t47) => {
1034
- const isKeyboard = t47 === undefined ? false : t47;
1035
- let deltaWithDirection;
1036
- if (isKeyboard) {
1037
- deltaWithDirection = delta;
1038
- } else {
1039
- deltaWithDirection = position === "end" ? -delta : delta;
1040
- }
1041
- updatePaneWidth(paneWidth + deltaWithDirection);
1042
- };
1043
- $[63] = paneWidth;
1044
- $[64] = position;
1045
- $[65] = updatePaneWidth;
1046
- $[66] = t46;
1047
- } else {
1048
- t46 = $[66];
1049
- }
1050
- let t47;
1051
- if ($[67] !== paneRef || $[68] !== updatePaneWidth) {
1052
- t47 = () => {
1053
- var _paneRef$current;
1054
- const paneRect = (_paneRef$current = paneRef.current) === null || _paneRef$current === void 0 ? void 0 : _paneRef$current.getBoundingClientRect();
1055
- if (!paneRect) {
1056
- return;
890
+ }), /*#__PURE__*/jsx(VerticalDivider, {
891
+ variant: isResponsiveValue(dividerProp) ? {
892
+ narrow: 'none',
893
+ regular: resizable ? 'line' : dividerProp.regular || 'none',
894
+ wide: resizable ? 'line' : dividerProp.wide || dividerProp.regular || 'none'
895
+ } : {
896
+ narrow: 'none',
897
+ // If pane is resizable, always show a vertical divider on regular viewports
898
+ regular: resizable ? 'line' : dividerVariant
1057
899
  }
1058
- updatePaneWidth(paneRect.width);
1059
- };
1060
- $[67] = paneRef;
1061
- $[68] = updatePaneWidth;
1062
- $[69] = t47;
1063
- } else {
1064
- t47 = $[69];
1065
- }
1066
- let t48;
1067
- if ($[70] !== updatePaneWidth || $[71] !== width) {
1068
- t48 = () => updatePaneWidth(getDefaultPaneWidth(width));
1069
- $[70] = updatePaneWidth;
1070
- $[71] = width;
1071
- $[72] = t48;
1072
- } else {
1073
- t48 = $[72];
1074
- }
1075
- const t49 = `var(--spacing-${columnGap})`;
1076
- let t50;
1077
- if ($[73] !== t49) {
1078
- t50 = {
1079
- "--spacing": t49
1080
- };
1081
- $[73] = t49;
1082
- $[74] = t50;
1083
- } else {
1084
- t50 = $[74];
1085
- }
1086
- const t51 = t50;
1087
- let t52;
1088
- if ($[75] !== positionProp || $[76] !== resizable || $[77] !== t45 || $[78] !== t46 || $[79] !== t47 || $[80] !== t48 || $[81] !== t51) {
1089
- t52 = /*#__PURE__*/jsx(VerticalDivider, {
1090
- variant: t45,
900
+ // If pane is resizable, the divider should be draggable
901
+ ,
1091
902
  draggable: resizable,
1092
- onDrag: t46,
1093
- onDragEnd: t47,
1094
- position: positionProp,
1095
- onDoubleClick: t48,
903
+ handleRef: handleRef,
904
+ onDrag: (delta, isKeyboard = false) => {
905
+ const deltaWithDirection = isKeyboard ? delta : position === 'end' ? -delta : delta;
906
+ const maxWidth = maxPaneWidthRef.current;
907
+ if (isKeyboard) {
908
+ // Clamp keyboard delta to stay within bounds
909
+ const newWidth = Math.max(minPaneWidth, Math.min(maxWidth, currentWidthRef.current + deltaWithDirection));
910
+ if (newWidth !== currentWidthRef.current) {
911
+ var _paneRef$current3;
912
+ currentWidthRef.current = newWidth;
913
+ (_paneRef$current3 = paneRef.current) === null || _paneRef$current3 === void 0 ? void 0 : _paneRef$current3.style.setProperty('--pane-width', `${newWidth}px`);
914
+ updateAriaValues(handleRef.current, {
915
+ current: newWidth
916
+ });
917
+ }
918
+ } else {
919
+ // Apply delta directly via CSS variable for immediate visual feedback
920
+ if (paneRef.current) {
921
+ const newWidth_0 = currentWidthRef.current + deltaWithDirection;
922
+ const clampedWidth = Math.max(minPaneWidth, Math.min(maxWidth, newWidth_0));
923
+
924
+ // Only update if the clamped width actually changed
925
+ // This prevents drift when dragging against min/max constraints
926
+ if (clampedWidth !== currentWidthRef.current) {
927
+ paneRef.current.style.setProperty('--pane-width', `${clampedWidth}px`);
928
+ currentWidthRef.current = clampedWidth;
929
+ updateAriaValues(handleRef.current, {
930
+ current: clampedWidth
931
+ });
932
+ }
933
+ }
934
+ }
935
+ }
936
+ // Save final width to localStorage (skip React state update to avoid reconciliation)
937
+ ,
938
+ onDragEnd: () => {
939
+ // For mouse drag: The CSS variable is already set and currentWidthRef is in sync.
940
+ // We intentionally skip setPaneWidth() to avoid triggering expensive React
941
+ // reconciliation with large DOM trees. The ref is the source of truth for
942
+ // subsequent drag operations.
943
+ setWidthInLocalStorage(currentWidthRef.current);
944
+ },
945
+ position: positionProp
946
+ // Reset pane width on double click
947
+ ,
948
+ onDoubleClick: () => {
949
+ const defaultWidth_0 = getDefaultPaneWidth(width);
950
+ // Update CSS variable and ref directly - skip React state to avoid reconciliation
951
+ if (paneRef.current) {
952
+ paneRef.current.style.setProperty('--pane-width', `${defaultWidth_0}px`);
953
+ currentWidthRef.current = defaultWidth_0;
954
+ updateAriaValues(handleRef.current, {
955
+ current: defaultWidth_0
956
+ });
957
+ }
958
+ setWidthInLocalStorage(defaultWidth_0);
959
+ },
1096
960
  className: classes.PaneVerticalDivider,
1097
- style: t51
1098
- });
1099
- $[75] = positionProp;
1100
- $[76] = resizable;
1101
- $[77] = t45;
1102
- $[78] = t46;
1103
- $[79] = t47;
1104
- $[80] = t48;
1105
- $[81] = t51;
1106
- $[82] = t52;
1107
- } else {
1108
- t52 = $[82];
1109
- }
1110
- let t53;
1111
- if ($[83] !== t19 || $[84] !== t24 || $[85] !== t25 || $[86] !== t26 || $[87] !== t27 || $[88] !== t32 || $[89] !== t44 || $[90] !== t52) {
1112
- t53 = /*#__PURE__*/jsxs("div", {
1113
- className: t19,
1114
- style: t24,
1115
- ...t25,
1116
- ...t26,
1117
- "data-sticky": t27,
1118
- children: [t32, t44, t52]
1119
- });
1120
- $[83] = t19;
1121
- $[84] = t24;
1122
- $[85] = t25;
1123
- $[86] = t26;
1124
- $[87] = t27;
1125
- $[88] = t32;
1126
- $[89] = t44;
1127
- $[90] = t52;
1128
- $[91] = t53;
1129
- } else {
1130
- t53 = $[91];
1131
- }
1132
- return t53;
961
+ style: {
962
+ '--spacing': `var(--spacing-${columnGap})`
963
+ }
964
+ })]
965
+ });
1133
966
  });
1134
967
  Pane.displayName = 'PageLayout.Pane';
1135
968
 
@@ -1288,15 +1121,14 @@ Header.__SLOT__ = Symbol('PageLayout.Header');
1288
1121
  Content.__SLOT__ = Symbol('PageLayout.Content');
1289
1122
  Pane.__SLOT__ = Symbol('PageLayout.Pane');
1290
1123
  Footer.__SLOT__ = Symbol('PageLayout.Footer');
1291
- function _temp(width_0) {
1292
- if (isPaneWidth(width_0)) {
1293
- return defaultPaneWidth[width_0];
1294
- } else {
1295
- if (isCustomWidthOptions(width_0)) {
1296
- return Number(width_0.default.split("px")[0]);
1297
- }
1298
- }
1299
- return 0;
1124
+ function _temp(event) {
1125
+ if (event.button !== 0) {
1126
+ return;
1127
+ }
1128
+ event.preventDefault();
1129
+ const target = event.currentTarget;
1130
+ target.setPointerCapture(event.pointerId);
1131
+ target.setAttribute(DATA_DRAGGING_ATTR, "true");
1300
1132
  }
1301
1133
 
1302
1134
  export { PageLayout };