Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/fast-meals-call.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@alfalab/core-components-bottom-sheet': patch
'@alfalab/core-components': patch
---

##### BottomSheet

- Исправлено нестабильное поведение `BottomSheet` при динамической смене `magneticAreas`.
- Если после обновления `magneticAreas` активный индекс выходит за границы массива (например, когда массив стал короче), компонент теперь переводит шторку в ближайшую доступную магнитную область вместо сброса в offset `0`. Это устраняет рывки и визуальные скачки, сохраняя ближайшую предыдущую высоту.
32 changes: 32 additions & 0 deletions packages/bottom-sheet/src/component.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,38 @@ describe('Bottom sheet', () => {
await waitFor(() => expect(onMagnetizeEnd).toHaveBeenCalledWith(1));
});

it('should remap active magnetic area after magneticAreas change', async () => {
const onMagnetize = jest.fn();

const { rerender } = render(
<BottomSheetWrapper
magneticAreas={[0, 200, 500]}
initialActiveAreaIndex={2}
onMagnetize={onMagnetize}
transitionProps={{
timeout: 0,
}}
/>,
);

await waitFor(() => expect(onMagnetize).toHaveBeenCalledWith(2));

onMagnetize.mockClear();

rerender(
<BottomSheetWrapper
magneticAreas={[0, 200]}
initialActiveAreaIndex={2}
onMagnetize={onMagnetize}
transitionProps={{
timeout: 0,
}}
/>,
);

await waitFor(() => expect(onMagnetize).toHaveBeenCalledWith(1));
});

it('should call onMagnetize and onMagnetizeEnd prop after closing', async () => {
const onMagnetize = jest.fn();
const onMagnetizeEnd = jest.fn();
Expand Down
32 changes: 32 additions & 0 deletions packages/bottom-sheet/src/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ export const BottomSheet = forwardRef<HTMLDivElement, BottomSheetProps>(
fullHeight = adjustContainerHeight(fullHeight);

const initialIndexRef = useRef<number | undefined>(initialActiveAreaIndex);
const prevMagneticAreasRef = useRef<number[]>();
const prevMagneticAreasPropRef = useRef<Array<number | string> | undefined>(
magneticAreasProp,
);
Expand Down Expand Up @@ -259,6 +260,25 @@ export const BottomSheet = forwardRef<HTMLDivElement, BottomSheetProps>(
};

const getActiveAreaIndex = (area?: number) => magneticAreas.findIndex((a) => a === area);
const getClosestAreaIndex = (area: number, areas: number[]) =>
areas.reduce(
(result, currentArea, currentIndex) => {
const distance = Math.abs(currentArea - area);

if (distance < result.distance) {
return {
distance,
index: currentIndex,
};
}

return result;
},
{
distance: Number.POSITIVE_INFINITY,
index: 0,
},
).index;

const setSheetHeight = () => {
if (sheetRef.current) {
Expand Down Expand Up @@ -552,8 +572,10 @@ export const BottomSheet = forwardRef<HTMLDivElement, BottomSheetProps>(
if (!isFirstRender) {
const magneticAreasPropChanged =
prevMagneticAreasPropRef.current !== magneticAreasProp;
const prevMagneticAreas = prevMagneticAreasRef.current;

prevMagneticAreasPropRef.current = magneticAreasProp;
prevMagneticAreasRef.current = magneticAreas;

if (magneticAreasPropChanged) {
setSkipTransition(true);
Expand All @@ -565,6 +587,16 @@ export const BottomSheet = forwardRef<HTMLDivElement, BottomSheetProps>(

setSheetOffset(isNil(idx) ? 0 : lastMagneticArea - magneticAreas[idx]);
setActiveAreaIdx(isNil(idx) ? magneticAreas.length - 1 : idx);
} else if (magneticAreasPropChanged && prevMagneticAreas?.length) {
const prevActiveArea =
prevMagneticAreas[activeAreaIdx] ??
prevMagneticAreas[prevMagneticAreas.length - 1];
const nextAreaIdx = getClosestAreaIndex(prevActiveArea, magneticAreas);
const nextArea = magneticAreas[nextAreaIdx];

setSheetOffset(lastMagneticArea - nextArea);
setActiveAreaIdx(nextAreaIdx);
onMagnetize?.(nextAreaIdx);
} else {
setSheetOffset(activeArea ? lastMagneticArea - activeArea : 0);
}
Expand Down
Loading