@moneyforward/mfui-components 3.10.1 → 3.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/src/Breadcrumbs/Breadcrumbs.d.ts +9 -0
  2. package/dist/src/Breadcrumbs/Breadcrumbs.js +150 -0
  3. package/dist/src/Breadcrumbs/Breadcrumbs.types.d.ts +31 -0
  4. package/dist/src/Breadcrumbs/Breadcrumbs.types.js +1 -0
  5. package/dist/src/Breadcrumbs/index.d.ts +2 -0
  6. package/dist/src/Breadcrumbs/index.js +1 -0
  7. package/dist/src/Button/Button.d.ts +1 -1
  8. package/dist/src/CheckboxGroup/CheckboxGroup.d.ts +1 -1
  9. package/dist/src/DataTable/index.d.ts +1 -0
  10. package/dist/src/DataTable/index.js +1 -0
  11. package/dist/src/DataTable/utils/getColumnWidthFromContentWidth.d.ts +27 -0
  12. package/dist/src/DataTable/utils/getColumnWidthFromContentWidth.js +35 -0
  13. package/dist/src/DateTimeSelection/DateRangePicker/DateRangePickerProvider/DateRangePickerProvider.d.ts +2 -2
  14. package/dist/src/DateTimeSelection/shared/BaseRangePicker/BaseRangePickerProvider/BaseRangePickerProvider.d.ts +2 -2
  15. package/dist/src/DateTimeSelection/shared/CalendarGrid/CalendarGrid.js +12 -2
  16. package/dist/src/IconButton/IconButton.d.ts +2 -2
  17. package/dist/src/MultipleSelectBox/MultipleSelectBox.d.ts +1 -1
  18. package/dist/src/MultipleSelectBox/MultipleSelectBox.js +5 -2
  19. package/dist/src/MultipleSelectBox/MultipleSelectBox.types.d.ts +9 -0
  20. package/dist/src/RadioButton/RadioButton.d.ts +1 -1
  21. package/dist/src/RadioGroup/RadioGroup.d.ts +1 -1
  22. package/dist/src/SplitView/SplitView.d.ts +7 -16
  23. package/dist/src/SplitView/SplitView.js +110 -70
  24. package/dist/src/SplitView/SplitView.types.d.ts +84 -56
  25. package/dist/src/SplitView/hooks/useSplitViewAnimation.d.ts +6 -6
  26. package/dist/src/SplitView/hooks/useSplitViewAnimation.js +46 -48
  27. package/dist/src/SplitView/hooks/useSplitViewDrag.d.ts +5 -4
  28. package/dist/src/SplitView/hooks/useSplitViewDrag.js +22 -12
  29. package/dist/src/SplitView/hooks/useSplitViewKeyboard.d.ts +7 -6
  30. package/dist/src/SplitView/hooks/useSplitViewKeyboard.js +22 -16
  31. package/dist/src/SplitView/hooks/useSplitViewPanelVisibility.d.ts +3 -3
  32. package/dist/src/SplitView/hooks/useSplitViewPanelVisibility.js +9 -9
  33. package/dist/src/SplitView/hooks/useSplitViewResize.d.ts +6 -6
  34. package/dist/src/SplitView/hooks/useSplitViewResize.js +16 -16
  35. package/dist/src/SplitView/utils/calculatePanelSize.d.ts +11 -11
  36. package/dist/src/SplitView/utils/calculatePanelSize.js +13 -13
  37. package/dist/src/SplitView/utils/styles.d.ts +21 -5
  38. package/dist/src/SplitView/utils/styles.js +47 -21
  39. package/dist/src/Stack/Stack.d.ts +7 -0
  40. package/dist/src/Stack/Stack.js +44 -38
  41. package/dist/src/Toast/ToastContainer/ToastContainer.d.ts +4 -0
  42. package/dist/src/Toast/ToastContainer/ToastContainer.js +11 -8
  43. package/dist/src/Tooltip/Tooltip.d.ts +2 -1
  44. package/dist/src/Tooltip/Tooltip.js +4 -2
  45. package/dist/src/Tooltip/Tooltip.types.d.ts +11 -0
  46. package/dist/src/index.d.ts +1 -0
  47. package/dist/src/index.js +1 -0
  48. package/dist/styled-system/recipes/breadcrumbs-slot-recipe.d.ts +33 -0
  49. package/dist/styled-system/recipes/breadcrumbs-slot-recipe.js +63 -0
  50. package/dist/styled-system/recipes/index.d.ts +1 -0
  51. package/dist/styled-system/recipes/index.js +1 -0
  52. package/dist/styles.css +88 -7
  53. package/dist/tsconfig.build.tsbuildinfo +1 -1
  54. package/package.json +2 -1
@@ -1,6 +1,6 @@
1
1
  import { useLayoutEffect } from 'react';
2
2
  import { ANIMATION_SIZE_THRESHOLD_PX } from '../constants';
3
- import { calculateInitialRightPanelSize } from '../utils/calculatePanelSize';
3
+ import { calculateInitialPanelSize } from '../utils/calculatePanelSize';
4
4
  import { createSlideInAnimation, createSlideOutAnimation } from '../utils/animation';
5
5
  /**
6
6
  * Hook to handle slide-in and slide-out animations for the split view.
@@ -8,20 +8,20 @@ import { createSlideInAnimation, createSlideOutAnimation } from '../utils/animat
8
8
  * @param options - Animation hook options
9
9
  */
10
10
  export function useSplitViewAnimation(options) {
11
- const { isRightPanelVisible, containerRef, initialRightPanelSize, minRightPanelSize, isInitialMountRef, wasRightPanelVisibleOnMountRef, previousIsRightPanelVisibleRef, hasRightPanelBeenVisible, isAnimating, rightPanelSize, lastRightPanelSizeRef, lastRightPanelRef, setRightPanelSize, setIsAnimating, setAnimatedRightPanelSize, setHasRightPanelBeenVisible, setIsSlideOutAnimating, } = options;
12
- // Track when right panel becomes visible to trigger animation (only when opened by trigger, not on initial mount)
11
+ const { isRightPanelVisible, containerRef, initialPanelSize, isInitialMountRef, wasRightPanelVisibleOnMountRef, previousIsRightPanelVisibleRef, hasRightPanelBeenVisible, isAnimating, controlledPanelSize, lastControlledPanelSizeRef, lastRightPanelRef, setControlledPanelSize, setIsAnimating, setAnimatedPanelSize, setHasRightPanelBeenVisible, setIsSlideOutAnimating, } = options;
12
+ // Track when the controlled panel becomes visible to trigger animation
13
+ // (only when opened by a user action, not on initial mount)
13
14
  useLayoutEffect(() => {
14
15
  const isInitialMount = isInitialMountRef.current;
15
16
  const previousIsRightPanelVisible = previousIsRightPanelVisibleRef.current;
16
17
  // Update previous visibility state at the start of layout effect
17
18
  previousIsRightPanelVisibleRef.current = isRightPanelVisible;
18
- // Handle initial mount: if right panel is already visible, set size without animation
19
+ // Handle initial mount: if panel is already visible, set size without animation
19
20
  if (isInitialMount && isRightPanelVisible && wasRightPanelVisibleOnMountRef.current) {
20
- // Use saved right panel size if available, otherwise use initialRightPanelSize
21
- const savedRightPanelSize = lastRightPanelSizeRef.current;
22
- const targetRightPanelSize = calculateInitialRightPanelSize(initialRightPanelSize, savedRightPanelSize);
23
- setRightPanelSize(targetRightPanelSize);
24
- lastRightPanelSizeRef.current = targetRightPanelSize;
21
+ const savedPanelSize = lastControlledPanelSizeRef.current;
22
+ const targetPanelSize = calculateInitialPanelSize(initialPanelSize, savedPanelSize);
23
+ setControlledPanelSize(targetPanelSize);
24
+ lastControlledPanelSizeRef.current = targetPanelSize;
25
25
  // hasRightPanelBeenVisible is already true from initial state, no need to set it
26
26
  isInitialMountRef.current = false;
27
27
  return;
@@ -30,63 +30,64 @@ export function useSplitViewAnimation(options) {
30
30
  if (isInitialMount) {
31
31
  isInitialMountRef.current = false;
32
32
  }
33
- // Animate slide-in only when right panel becomes visible after initial mount (triggered by user action)
34
- // Check if right panel just became visible (transition from hidden to visible)
33
+ // Animate slide-in only when the controlled panel becomes visible after initial mount
34
+ // (i.e., triggered by a user action, not on first render)
35
35
  const justBecameVisible = isRightPanelVisible && !previousIsRightPanelVisible && !hasRightPanelBeenVisible;
36
36
  if (justBecameVisible && !isAnimating && !isInitialMount) {
37
- // Use saved right panel size if available, otherwise use initialRightPanelSize
38
- const savedRightPanelSize = lastRightPanelSizeRef.current;
39
- const targetRightPanelSize = calculateInitialRightPanelSize(initialRightPanelSize, savedRightPanelSize);
40
- // Start animation from 0px (right panel hidden)
37
+ const savedPanelSize = lastControlledPanelSizeRef.current;
38
+ const targetPanelSize = calculateInitialPanelSize(initialPanelSize, savedPanelSize);
39
+ // Start animation from 0 (panel hidden)
41
40
  const startSize = 0;
42
- // Only animate if there's a visual difference
43
- if (Math.abs(targetRightPanelSize - startSize) < ANIMATION_SIZE_THRESHOLD_PX) {
44
- // No animation needed, set directly
45
- setRightPanelSize(targetRightPanelSize);
46
- lastRightPanelSizeRef.current = targetRightPanelSize;
41
+ // Skip animation if the size difference is negligible
42
+ if (Math.abs(targetPanelSize - startSize) < ANIMATION_SIZE_THRESHOLD_PX) {
43
+ setControlledPanelSize(targetPanelSize);
44
+ lastControlledPanelSizeRef.current = targetPanelSize;
47
45
  setHasRightPanelBeenVisible(true);
48
46
  return;
49
47
  }
50
- // Immediately set the right panel size to avoid layout shift flash
51
- setRightPanelSize(startSize);
48
+ // Store the target size before animation so the inner wrapper can maintain
49
+ // the correct fixed width from the very first frame.
50
+ lastControlledPanelSizeRef.current = targetPanelSize;
51
+ // Immediately set the panel size to avoid layout shift flash
52
+ setControlledPanelSize(startSize);
52
53
  setIsAnimating(true);
53
- setAnimatedRightPanelSize(startSize);
54
+ setAnimatedPanelSize(startSize);
54
55
  setHasRightPanelBeenVisible(true);
55
56
  createSlideInAnimation({
56
57
  startSize,
57
- targetSize: targetRightPanelSize,
58
+ targetSize: targetPanelSize,
58
59
  onUpdate: (size) => {
59
- setAnimatedRightPanelSize(size);
60
+ setAnimatedPanelSize(size);
60
61
  },
61
62
  onComplete: () => {
62
63
  setIsAnimating(false);
63
- setAnimatedRightPanelSize(undefined);
64
- setRightPanelSize(targetRightPanelSize);
65
- lastRightPanelSizeRef.current = targetRightPanelSize;
64
+ setAnimatedPanelSize(undefined);
65
+ setControlledPanelSize(targetPanelSize);
66
+ lastControlledPanelSizeRef.current = targetPanelSize;
66
67
  },
67
68
  });
68
69
  }
69
- // Slide-out animation: right panel becomes hidden
70
+ // Slide-out animation: controlled panel becomes hidden
70
71
  if (!isRightPanelVisible && hasRightPanelBeenVisible) {
71
72
  if (containerRef.current && !isAnimating) {
72
- // Start from current right panel size
73
- const startSize = lastRightPanelSizeRef.current ?? rightPanelSize ?? 0;
74
- // Animate to 0px (right panel hidden)
73
+ // Start from current controlled panel size
74
+ const startSize = lastControlledPanelSizeRef.current ?? controlledPanelSize ?? 0;
75
+ // Animate to 0 (panel hidden)
75
76
  const targetSize = 0;
76
77
  setIsAnimating(true);
77
78
  setIsSlideOutAnimating(true);
78
- setAnimatedRightPanelSize(startSize);
79
+ setAnimatedPanelSize(startSize);
79
80
  createSlideOutAnimation({
80
81
  startSize,
81
82
  targetSize,
82
83
  onUpdate: (size) => {
83
- setAnimatedRightPanelSize(size);
84
+ setAnimatedPanelSize(size);
84
85
  },
85
86
  onComplete: () => {
86
87
  setIsAnimating(false);
87
88
  setIsSlideOutAnimating(false);
88
- setAnimatedRightPanelSize(undefined);
89
- setRightPanelSize(undefined);
89
+ setAnimatedPanelSize(undefined);
90
+ setControlledPanelSize(undefined);
90
91
  setHasRightPanelBeenVisible(false);
91
92
  // Clear stored content after animation completes
92
93
  lastRightPanelRef.current = null;
@@ -94,32 +95,29 @@ export function useSplitViewAnimation(options) {
94
95
  });
95
96
  }
96
97
  else {
97
- // No animation - immediately reset
98
- // Save current right panel size before closing
99
- if (rightPanelSize !== undefined) {
100
- lastRightPanelSizeRef.current = rightPanelSize;
98
+ // No animation immediately reset
99
+ if (controlledPanelSize !== undefined) {
100
+ lastControlledPanelSizeRef.current = controlledPanelSize;
101
101
  }
102
102
  setHasRightPanelBeenVisible(false);
103
- // Reset right panel size to allow left panel to take full width
104
- setRightPanelSize(undefined);
103
+ setControlledPanelSize(undefined);
105
104
  }
106
105
  }
107
106
  }, [
108
107
  isRightPanelVisible,
109
108
  containerRef,
110
- initialRightPanelSize,
111
- minRightPanelSize,
109
+ initialPanelSize,
112
110
  isInitialMountRef,
113
111
  wasRightPanelVisibleOnMountRef,
114
112
  previousIsRightPanelVisibleRef,
115
113
  hasRightPanelBeenVisible,
116
114
  isAnimating,
117
- rightPanelSize,
118
- lastRightPanelSizeRef,
115
+ controlledPanelSize,
116
+ lastControlledPanelSizeRef,
119
117
  lastRightPanelRef,
120
- setRightPanelSize,
118
+ setControlledPanelSize,
121
119
  setIsAnimating,
122
- setAnimatedRightPanelSize,
120
+ setAnimatedPanelSize,
123
121
  setHasRightPanelBeenVisible,
124
122
  setIsSlideOutAnimating,
125
123
  ]);
@@ -5,10 +5,11 @@
5
5
  */
6
6
  export declare function useSplitViewDrag(options: {
7
7
  containerRef: React.RefObject<HTMLDivElement | null>;
8
- minRightPanelSize: number;
9
- maxRightPanelSize: number;
10
- setRightPanelSize: (size: number | undefined) => void;
11
- setLastRightPanelSize: (size: number | undefined) => void;
8
+ targetPanel: 'left' | 'right';
9
+ minPanelSize: number;
10
+ maxPanelSize: number;
11
+ setControlledPanelSize: (size: number | undefined) => void;
12
+ setLastControlledPanelSize: (size: number | undefined) => void;
12
13
  }): {
13
14
  isDragging: boolean;
14
15
  handleMouseDown: (event: React.PointerEvent<HTMLDivElement>) => void;
@@ -1,16 +1,16 @@
1
1
  import { useCallback, useEffect, useRef, useState } from 'react';
2
- import { calculateConstrainedRightPanelSize } from '../utils/calculatePanelSize';
2
+ import { calculateConstrainedPanelSize } from '../utils/calculatePanelSize';
3
3
  /**
4
4
  * Hook to handle drag interactions for resizing the split view.
5
5
  *
6
6
  * @param options - Drag hook options
7
7
  */
8
8
  export function useSplitViewDrag(options) {
9
- const { containerRef, minRightPanelSize, maxRightPanelSize, setRightPanelSize, setLastRightPanelSize } = options;
9
+ const { containerRef, targetPanel, minPanelSize, maxPanelSize, setControlledPanelSize, setLastControlledPanelSize } = options;
10
10
  const [isDragging, setIsDragging] = useState(false);
11
11
  const pointerIdRef = useRef(null);
12
12
  /**
13
- * Handle pointer down on the divider
13
+ * Handle pointer down on the divider.
14
14
  */
15
15
  const handlePointerDown = useCallback((event) => {
16
16
  event.preventDefault();
@@ -20,7 +20,7 @@ export function useSplitViewDrag(options) {
20
20
  setIsDragging(true);
21
21
  }, []);
22
22
  /**
23
- * Handle pointer move during drag
23
+ * Handle pointer move during drag.
24
24
  */
25
25
  const handlePointerMove = useCallback((event) => {
26
26
  if (!isDragging || pointerIdRef.current !== event.pointerId)
@@ -29,14 +29,24 @@ export function useSplitViewDrag(options) {
29
29
  return;
30
30
  const containerRect = containerRef.current.getBoundingClientRect();
31
31
  const containerSize = containerRect.width;
32
- const rawRightPanelSize = containerSize - (event.clientX - containerRect.left);
33
- // Apply min/max constraints directly to right panel size
34
- const constrainedRightPanelSize = calculateConstrainedRightPanelSize(rawRightPanelSize, minRightPanelSize, maxRightPanelSize);
35
- setRightPanelSize(constrainedRightPanelSize);
36
- setLastRightPanelSize(constrainedRightPanelSize);
37
- }, [isDragging, containerRef, minRightPanelSize, maxRightPanelSize, setRightPanelSize, setLastRightPanelSize]);
32
+ // Compute raw controlled panel size based on which panel is being controlled
33
+ const rawControlledPanelSize = targetPanel === 'left'
34
+ ? event.clientX - containerRect.left // left panel size = pointer X from container left
35
+ : containerSize - (event.clientX - containerRect.left); // right panel size (legacy behavior)
36
+ const constrainedSize = calculateConstrainedPanelSize(rawControlledPanelSize, minPanelSize, maxPanelSize);
37
+ setControlledPanelSize(constrainedSize);
38
+ setLastControlledPanelSize(constrainedSize);
39
+ }, [
40
+ isDragging,
41
+ containerRef,
42
+ targetPanel,
43
+ minPanelSize,
44
+ maxPanelSize,
45
+ setControlledPanelSize,
46
+ setLastControlledPanelSize,
47
+ ]);
38
48
  /**
39
- * Handle pointer up to stop dragging
49
+ * Handle pointer up to stop dragging.
40
50
  */
41
51
  const handlePointerUp = useCallback((event) => {
42
52
  if (pointerIdRef.current === event.pointerId) {
@@ -45,7 +55,7 @@ export function useSplitViewDrag(options) {
45
55
  }
46
56
  }, []);
47
57
  /**
48
- * Set up pointer event listeners
58
+ * Set up pointer event listeners.
49
59
  */
50
60
  useEffect(() => {
51
61
  if (!isDragging)
@@ -5,12 +5,13 @@
5
5
  */
6
6
  export declare function useSplitViewKeyboard(options: {
7
7
  containerRef: React.RefObject<HTMLDivElement | null>;
8
- rightPanelSize: number | undefined;
9
- initialRightPanelSize: number;
10
- minRightPanelSize: number;
11
- maxRightPanelSize: number;
12
- setRightPanelSize: (size: number | undefined) => void;
13
- setLastRightPanelSize: (size: number | undefined) => void;
8
+ targetPanel: 'left' | 'right';
9
+ controlledPanelSize: number | undefined;
10
+ initialPanelSize: number;
11
+ minPanelSize: number;
12
+ maxPanelSize: number;
13
+ setControlledPanelSize: (size: number | undefined) => void;
14
+ setLastControlledPanelSize: (size: number | undefined) => void;
14
15
  }): {
15
16
  handleKeyDown: (event: React.KeyboardEvent<HTMLDivElement>) => void;
16
17
  };
@@ -1,25 +1,31 @@
1
1
  import { useCallback } from 'react';
2
2
  import { KEYBOARD_STEP_PX } from '../constants';
3
- import { calculateConstrainedRightPanelSize } from '../utils/calculatePanelSize';
3
+ import { calculateConstrainedPanelSize } from '../utils/calculatePanelSize';
4
4
  /**
5
5
  * Hook to handle keyboard navigation for resizing the split view.
6
6
  *
7
7
  * @param options - Keyboard hook options
8
8
  */
9
9
  export function useSplitViewKeyboard(options) {
10
- const { containerRef, rightPanelSize, initialRightPanelSize, minRightPanelSize, maxRightPanelSize, setRightPanelSize, setLastRightPanelSize, } = options;
10
+ const { containerRef, targetPanel, controlledPanelSize, initialPanelSize, minPanelSize, maxPanelSize, setControlledPanelSize, setLastControlledPanelSize, } = options;
11
11
  /**
12
- * Handle keyboard navigation for the divider
12
+ * Handle keyboard navigation for the divider.
13
+ *
14
+ * Key directions depend on targetPanel:
15
+ * - targetPanel="right": ArrowLeft expands the right panel, ArrowRight shrinks it
16
+ * - targetPanel="left": ArrowRight expands the left panel, ArrowLeft shrinks it
13
17
  */
14
18
  const handleKeyDown = useCallback((event) => {
15
19
  if (!containerRef.current)
16
20
  return;
17
- const increaseKeys = ['ArrowLeft'];
18
- const decreaseKeys = ['ArrowRight'];
21
+ // Key-to-action mapping varies by targetPanel to keep UX intuitive:
22
+ // the divider always moves in the direction of the pressed arrow key.
23
+ const increaseKeys = targetPanel === 'left' ? ['ArrowRight'] : ['ArrowLeft'];
24
+ const decreaseKeys = targetPanel === 'left' ? ['ArrowLeft'] : ['ArrowRight'];
19
25
  if (![...increaseKeys, ...decreaseKeys].includes(event.key))
20
26
  return;
21
27
  event.preventDefault();
22
- const currentSize = rightPanelSize ?? initialRightPanelSize;
28
+ const currentSize = controlledPanelSize ?? initialPanelSize;
23
29
  let newSize = currentSize;
24
30
  if (increaseKeys.includes(event.key)) {
25
31
  newSize = currentSize + KEYBOARD_STEP_PX;
@@ -27,18 +33,18 @@ export function useSplitViewKeyboard(options) {
27
33
  else if (decreaseKeys.includes(event.key)) {
28
34
  newSize = currentSize - KEYBOARD_STEP_PX;
29
35
  }
30
- // Apply min/max constraints directly to right panel size
31
- const constrainedSize = calculateConstrainedRightPanelSize(newSize, minRightPanelSize, maxRightPanelSize);
32
- setRightPanelSize(constrainedSize);
33
- setLastRightPanelSize(constrainedSize);
36
+ const constrainedSize = calculateConstrainedPanelSize(newSize, minPanelSize, maxPanelSize);
37
+ setControlledPanelSize(constrainedSize);
38
+ setLastControlledPanelSize(constrainedSize);
34
39
  }, [
35
40
  containerRef,
36
- rightPanelSize,
37
- initialRightPanelSize,
38
- minRightPanelSize,
39
- maxRightPanelSize,
40
- setRightPanelSize,
41
- setLastRightPanelSize,
41
+ targetPanel,
42
+ controlledPanelSize,
43
+ initialPanelSize,
44
+ minPanelSize,
45
+ maxPanelSize,
46
+ setControlledPanelSize,
47
+ setLastControlledPanelSize,
42
48
  ]);
43
49
  return { handleKeyDown };
44
50
  }
@@ -1,14 +1,14 @@
1
1
  import { type ReactNode } from 'react';
2
2
  /**
3
- * Hook to manage the visibility state of the right panel.
3
+ * Hook to manage the visibility state of the controlled panel.
4
4
  *
5
5
  * @param isOpen - Controlled visibility state (optional)
6
6
  *
7
- * @param rightPanelSlot - The right panel content
7
+ * @param controlledPanelSlot - The content of the controlled panel (left or right depending on targetPanel)
8
8
  *
9
9
  * @returns Object containing visibility state and related refs
10
10
  */
11
- export declare function useSplitViewPanelVisibility(isOpen: boolean | undefined, rightPanelSlot: ReactNode): {
11
+ export declare function useSplitViewPanelVisibility(isOpen: boolean | undefined, controlledPanelSlot: ReactNode): {
12
12
  isRightPanelVisible: boolean;
13
13
  isInitialMountRef: import("react").RefObject<boolean>;
14
14
  wasRightPanelVisibleOnMountRef: import("react").RefObject<boolean | null>;
@@ -1,19 +1,19 @@
1
1
  import { useEffect, useRef, useState } from 'react';
2
2
  /**
3
- * Hook to manage the visibility state of the right panel.
3
+ * Hook to manage the visibility state of the controlled panel.
4
4
  *
5
5
  * @param isOpen - Controlled visibility state (optional)
6
6
  *
7
- * @param rightPanelSlot - The right panel content
7
+ * @param controlledPanelSlot - The content of the controlled panel (left or right depending on targetPanel)
8
8
  *
9
9
  * @returns Object containing visibility state and related refs
10
10
  */
11
- export function useSplitViewPanelVisibility(isOpen, rightPanelSlot) {
12
- // Determine if right panel should be visible (controlled by isOpen prop only)
11
+ export function useSplitViewPanelVisibility(isOpen, controlledPanelSlot) {
12
+ // Determine if the controlled panel should be visible (controlled by isOpen prop only)
13
13
  const isRightPanelVisible = isOpen ?? true;
14
14
  // Track if this is the initial mount
15
15
  const isInitialMountRef = useRef(true);
16
- // Track if right panel was visible on initial mount
16
+ // Track if the controlled panel was visible on initial mount
17
17
  const wasRightPanelVisibleOnMountRef = useRef(null);
18
18
  // Initialize wasRightPanelVisibleOnMountRef on first render only
19
19
  if (wasRightPanelVisibleOnMountRef.current === null) {
@@ -24,14 +24,14 @@ export function useSplitViewPanelVisibility(isOpen, rightPanelSlot) {
24
24
  // Track previous visibility state
25
25
  // Note: This ref is updated in useSplitViewAnimation hook to ensure correct timing
26
26
  const previousIsRightPanelVisibleRef = useRef(isRightPanelVisible);
27
- // Store last seen right panel for slide-out animation
27
+ // Store last seen controlled panel slot for slide-out animation
28
28
  const lastRightPanelRef = useRef(null);
29
- // Store right panel when visible for slide-out animation
29
+ // Store controlled panel slot when visible for use during slide-out animation
30
30
  useEffect(() => {
31
31
  if (isRightPanelVisible) {
32
- lastRightPanelRef.current = rightPanelSlot;
32
+ lastRightPanelRef.current = controlledPanelSlot;
33
33
  }
34
- }, [rightPanelSlot, isRightPanelVisible]);
34
+ }, [controlledPanelSlot, isRightPanelVisible]);
35
35
  return {
36
36
  isRightPanelVisible,
37
37
  isInitialMountRef,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Hook to handle container resize: maintain right panel size and apply constraints.
2
+ * Hook to handle container resize: maintain controlled panel size and apply constraints.
3
3
  *
4
4
  * @param options - Resize hook options
5
5
  */
@@ -8,9 +8,9 @@ export declare function useSplitViewResize(options: {
8
8
  containerRef: React.RefObject<HTMLDivElement | null>;
9
9
  isAnimating: boolean;
10
10
  isDragging: boolean;
11
- rightPanelSize: number | undefined;
12
- minRightPanelSize: number;
13
- maxRightPanelSize: number;
14
- setRightPanelSize: (size: number | undefined) => void;
15
- setLastRightPanelSize: (size: number | undefined) => void;
11
+ controlledPanelSize: number | undefined;
12
+ minPanelSize: number;
13
+ maxPanelSize: number;
14
+ setControlledPanelSize: (size: number | undefined) => void;
15
+ setLastControlledPanelSize: (size: number | undefined) => void;
16
16
  }): void;
@@ -1,12 +1,12 @@
1
1
  import { useEffect } from 'react';
2
- import { calculateConstrainedRightPanelSize } from '../utils/calculatePanelSize';
2
+ import { calculateConstrainedPanelSize } from '../utils/calculatePanelSize';
3
3
  /**
4
- * Hook to handle container resize: maintain right panel size and apply constraints.
4
+ * Hook to handle container resize: maintain controlled panel size and apply constraints.
5
5
  *
6
6
  * @param options - Resize hook options
7
7
  */
8
8
  export function useSplitViewResize(options) {
9
- const { isRightPanelVisible, containerRef, isAnimating, isDragging, rightPanelSize, minRightPanelSize, maxRightPanelSize, setRightPanelSize, setLastRightPanelSize, } = options;
9
+ const { isRightPanelVisible, containerRef, isAnimating, isDragging, controlledPanelSize, minPanelSize, maxPanelSize, setControlledPanelSize, setLastControlledPanelSize, } = options;
10
10
  useEffect(() => {
11
11
  if (!isRightPanelVisible || !containerRef.current || isAnimating || isDragging)
12
12
  return;
@@ -14,15 +14,15 @@ export function useSplitViewResize(options) {
14
14
  const resizeObserver = new ResizeObserver((entries) => {
15
15
  for (const entry of entries) {
16
16
  const containerSize = entry.contentRect.width;
17
- const currentRightPanelSize = rightPanelSize;
18
- if (currentRightPanelSize !== undefined) {
19
- // Ensure right panel size doesn't exceed container size
20
- const maxAllowedSize = Math.min(maxRightPanelSize, containerSize);
21
- const constrainedRightPanelSize = calculateConstrainedRightPanelSize(currentRightPanelSize, minRightPanelSize, maxAllowedSize);
17
+ const currentControlledPanelSize = controlledPanelSize;
18
+ if (currentControlledPanelSize !== undefined) {
19
+ // Controlled panel size must not exceed container size
20
+ const maxAllowedSize = Math.min(maxPanelSize, containerSize);
21
+ const constrainedSize = calculateConstrainedPanelSize(currentControlledPanelSize, minPanelSize, maxAllowedSize);
22
22
  // Only update if constraints were applied
23
- if (constrainedRightPanelSize !== currentRightPanelSize) {
24
- setRightPanelSize(constrainedRightPanelSize);
25
- setLastRightPanelSize(constrainedRightPanelSize);
23
+ if (constrainedSize !== currentControlledPanelSize) {
24
+ setControlledPanelSize(constrainedSize);
25
+ setLastControlledPanelSize(constrainedSize);
26
26
  }
27
27
  }
28
28
  }
@@ -36,10 +36,10 @@ export function useSplitViewResize(options) {
36
36
  containerRef,
37
37
  isAnimating,
38
38
  isDragging,
39
- rightPanelSize,
40
- minRightPanelSize,
41
- maxRightPanelSize,
42
- setRightPanelSize,
43
- setLastRightPanelSize,
39
+ controlledPanelSize,
40
+ minPanelSize,
41
+ maxPanelSize,
42
+ setControlledPanelSize,
43
+ setLastControlledPanelSize,
44
44
  ]);
45
45
  }
@@ -1,22 +1,22 @@
1
1
  /**
2
- * Calculate the right panel size with min/max constraints applied.
2
+ * Calculate the panel size with min/max constraints applied.
3
3
  *
4
- * @param rightPanelSize - The desired right panel size
4
+ * @param panelSize - The desired panel size
5
5
  *
6
- * @param minRightPanelSize - The minimum size of the right panel
6
+ * @param minPanelSize - The minimum size of the panel
7
7
  *
8
- * @param maxRightPanelSize - The maximum size of the right panel
8
+ * @param maxPanelSize - The maximum size of the panel
9
9
  *
10
- * @returns The constrained right panel size
10
+ * @returns The constrained panel size
11
11
  */
12
- export declare function calculateConstrainedRightPanelSize(rightPanelSize: number, minRightPanelSize: number, maxRightPanelSize: number): number;
12
+ export declare function calculateConstrainedPanelSize(panelSize: number, minPanelSize: number, maxPanelSize: number): number;
13
13
  /**
14
- * Calculate the initial right panel size based on props and saved state.
14
+ * Calculate the initial controlled panel size based on props and saved state.
15
15
  *
16
- * @param initialRightPanelSize - The initial right panel size prop
16
+ * @param initialPanelSize - The initial panel size prop
17
17
  *
18
- * @param savedRightPanelSize - The saved right panel size from previous state (optional)
18
+ * @param savedPanelSize - The saved panel size from previous state (optional)
19
19
  *
20
- * @returns The calculated right panel size
20
+ * @returns The calculated panel size
21
21
  */
22
- export declare function calculateInitialRightPanelSize(initialRightPanelSize: number, savedRightPanelSize?: number): number;
22
+ export declare function calculateInitialPanelSize(initialPanelSize: number, savedPanelSize?: number): number;
@@ -1,26 +1,26 @@
1
1
  /**
2
- * Calculate the right panel size with min/max constraints applied.
2
+ * Calculate the panel size with min/max constraints applied.
3
3
  *
4
- * @param rightPanelSize - The desired right panel size
4
+ * @param panelSize - The desired panel size
5
5
  *
6
- * @param minRightPanelSize - The minimum size of the right panel
6
+ * @param minPanelSize - The minimum size of the panel
7
7
  *
8
- * @param maxRightPanelSize - The maximum size of the right panel
8
+ * @param maxPanelSize - The maximum size of the panel
9
9
  *
10
- * @returns The constrained right panel size
10
+ * @returns The constrained panel size
11
11
  */
12
- export function calculateConstrainedRightPanelSize(rightPanelSize, minRightPanelSize, maxRightPanelSize) {
13
- return Math.max(minRightPanelSize, Math.min(rightPanelSize, maxRightPanelSize));
12
+ export function calculateConstrainedPanelSize(panelSize, minPanelSize, maxPanelSize) {
13
+ return Math.max(minPanelSize, Math.min(panelSize, maxPanelSize));
14
14
  }
15
15
  /**
16
- * Calculate the initial right panel size based on props and saved state.
16
+ * Calculate the initial controlled panel size based on props and saved state.
17
17
  *
18
- * @param initialRightPanelSize - The initial right panel size prop
18
+ * @param initialPanelSize - The initial panel size prop
19
19
  *
20
- * @param savedRightPanelSize - The saved right panel size from previous state (optional)
20
+ * @param savedPanelSize - The saved panel size from previous state (optional)
21
21
  *
22
- * @returns The calculated right panel size
22
+ * @returns The calculated panel size
23
23
  */
24
- export function calculateInitialRightPanelSize(initialRightPanelSize, savedRightPanelSize) {
25
- return savedRightPanelSize ?? initialRightPanelSize;
24
+ export function calculateInitialPanelSize(initialPanelSize, savedPanelSize) {
25
+ return savedPanelSize ?? initialPanelSize;
26
26
  }
@@ -13,18 +13,34 @@ export declare function calculateDividerStyle(options: {
13
13
  dividerPropsStyle?: CSSProperties;
14
14
  }): CSSProperties;
15
15
  /**
16
- * Calculate the right panel style based on the current size state, visibility, and animation state.
16
+ * Styles returned for the controlled panel: the outer div handles layout and animation,
17
+ * the inner div maintains a fixed width during animation to prevent content reflow.
18
+ */
19
+ export type ControlledPanelStyles = {
20
+ /** Applied to the panel div (the flex item). */
21
+ outer: CSSProperties;
22
+ /**
23
+ * Applied to an inner wrapper div that wraps the panel's slot content.
24
+ * Maintains a fixed width during animation so the content never reflows.
25
+ */
26
+ inner: CSSProperties;
27
+ };
28
+ /**
29
+ * Calculate the controlled panel style based on the current size state, visibility, and animation state.
17
30
  *
18
31
  * @param options - Style calculation options
19
32
  *
20
- * @returns The style object for the right panel
33
+ * @returns Styles for the outer panel div and the inner content wrapper div.
21
34
  */
22
- export declare function calculateRightPanelStyleUnified(options: {
35
+ export declare function calculateControlledPanelStyle(options: {
23
36
  currentSize: number | undefined;
37
+ /** The full open size of the panel, used to fix the inner wrapper width during animation. */
38
+ fullPanelSize: number;
39
+ targetPanel: 'left' | 'right';
24
40
  enableAutoUnmount: boolean;
25
41
  isRightPanelVisible: boolean;
26
42
  isSlideOutAnimating: boolean;
27
43
  hasRightPanelBeenVisible: boolean;
28
44
  isAnimating: boolean;
29
- rightPanelPropsStyle?: CSSProperties;
30
- }): CSSProperties;
45
+ panelPropsStyle?: CSSProperties;
46
+ }): ControlledPanelStyles;