Skip to content

Commit aaba185

Browse files
committed
better opening and closing
1 parent 61f6ef2 commit aaba185

File tree

2 files changed

+41
-38
lines changed

2 files changed

+41
-38
lines changed

src/hooks/use-sheet-state.ts

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,56 +5,42 @@ type SheetState = 'closed' | 'opening' | 'open' | 'closing';
55

66
type UseSheetStatesProps = {
77
isOpen: boolean;
8-
onClosed?: () => Promise<void> | void;
98
onOpening?: () => Promise<void> | void;
10-
onOpen?: () => Promise<void> | void;
119
onClosing?: () => Promise<void> | void;
1210
};
1311

1412
export function useSheetState({
1513
isOpen,
16-
onClosed: _onClosed,
1714
onOpening: _onOpening,
18-
onOpen: _onOpen,
1915
onClosing: _onClosing,
2016
}: UseSheetStatesProps) {
2117
const [state, setState] = useState<SheetState>(isOpen ? 'opening' : 'closed');
2218
const abortControllerRef = useRef<AbortController | null>(null);
23-
const onClosed = useStableCallback(() => _onClosed?.());
2419
const onOpening = useStableCallback(() => _onOpening?.());
25-
const onOpen = useStableCallback(() => _onOpen?.());
2620
const onClosing = useStableCallback(() => _onClosing?.());
2721

2822
useEffect(() => {
2923
abortControllerRef.current?.abort();
30-
setState(isOpen ? 'opening' : 'closing');
31-
}, [isOpen]);
3224

33-
useEffect(() => {
3425
const abortController = new AbortController();
3526
abortControllerRef.current = abortController;
3627

3728
async function handle() {
38-
switch (state) {
39-
case 'closed':
40-
await onClosed?.();
41-
break;
42-
43-
case 'opening':
29+
switch (isOpen) {
30+
case true:
31+
setState('opening');
4432
await onOpening?.();
4533
if (!abortController.signal.aborted) setState('open');
4634
break;
4735

48-
case 'open':
49-
await onOpen?.();
50-
break;
51-
52-
case 'closing':
36+
case false:
37+
setState('closing');
5338
await onClosing?.();
5439
if (!abortController.signal.aborted) setState('closed');
5540
break;
5641
}
5742
}
43+
5844
handle().catch((error) => {
5945
if (error instanceof Error) {
6046
console.error('Internal sheet state error:', error);
@@ -64,7 +50,7 @@ export function useSheetState({
6450
return () => {
6551
abortController.abort();
6652
};
67-
}, [state]);
53+
}, [isOpen]);
6854

6955
return state;
7056
}

src/sheet.tsx

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -507,14 +507,19 @@ export const Sheet = forwardRef<any, SheetProps>(
507507
const initialSnapPoint =
508508
initialSnap !== undefined ? getSnapPoint(initialSnap) : null;
509509

510+
const onAnimationComplete = makeCallableSingleTime(() => {
511+
clearYListeners();
512+
handleOpenEnd();
513+
resolve();
514+
});
515+
510516
if (!initialSnapPoint) {
511517
console.warn(
512518
'No initial snap point found',
513519
initialSnap,
514520
snapPoints
515521
);
516-
handleOpenEnd();
517-
resolve();
522+
onAnimationComplete();
518523
return;
519524
}
520525

@@ -527,20 +532,17 @@ export const Sheet = forwardRef<any, SheetProps>(
527532
y.on('animationCancel', () => {
528533
clearYListeners();
529534
if (openStateRef.current === 'opening') {
530-
handleOpenEnd();
531-
resolve();
535+
onAnimationComplete();
532536
} else {
533537
reject('stopped opening');
534538
}
535539
}),
536-
y.on('animationComplete', () => {
537-
clearYListeners();
538-
handleOpenEnd();
539-
resolve();
540-
})
540+
y.on('animationComplete', onAnimationComplete)
541541
);
542542

543-
animate(y, initialSnapPoint.snapValueY, animationOptions);
543+
animate(y, initialSnapPoint.snapValueY, animationOptions).then(
544+
onAnimationComplete
545+
);
544546
}
545547
};
546548

@@ -575,30 +577,36 @@ export const Sheet = forwardRef<any, SheetProps>(
575577
openStateRef.current = 'closed';
576578
};
577579

580+
const onAnimationComplete = makeCallableSingleTime(() => {
581+
clearYListeners();
582+
handleCloseEnd();
583+
resolve();
584+
});
585+
578586
yListenersRef.current.push(
579587
y.on('animationCancel', () => {
580588
clearYListeners();
581589

582590
if (openStateRef.current === 'closing') {
583-
handleCloseEnd();
584-
resolve();
591+
onAnimationComplete();
585592
} else {
586593
reject('stopped closing');
587594
}
588595
}),
589596
y.on('animationComplete', () => {
590-
clearYListeners();
591-
592-
handleCloseEnd();
593-
resolve();
597+
onAnimationComplete();
594598
})
595599
);
596600

597-
animate(y, closedY, animationOptions);
601+
animate(y, closedY, animationOptions).then(() => {
602+
onAnimationComplete();
603+
});
598604
});
599605
},
600606
});
601607

608+
console.log(rest.id, 'isOpen', isOpen, 'state', state);
609+
602610
const dragProps: SheetContextType['dragProps'] = {
603611
drag: 'y',
604612
dragElastic: 0,
@@ -668,3 +676,12 @@ function linear(
668676
);
669677
return outputMin + (outputMax - outputMin) * t;
670678
}
679+
680+
function makeCallableSingleTime<T>(fn: () => T) {
681+
let called = false;
682+
return () => {
683+
if (called) return;
684+
called = true;
685+
fn();
686+
};
687+
}

0 commit comments

Comments
 (0)