@seed-design/react-drawer 1.0.7 → 1.0.9
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.
- package/lib/{Drawer-12s-1gup1cyj.js → Drawer-12s-B-JAOvwq.js} +103 -29
- package/lib/{Drawer-12s-L4KZ1h_g.cjs → Drawer-12s-B35ZJcKm.cjs} +102 -27
- package/lib/index.cjs +3 -1
- package/lib/index.d.ts +133 -41
- package/lib/index.js +4 -3
- package/package.json +2 -2
- package/src/Drawer.namespace.ts +2 -0
- package/src/Drawer.tsx +34 -13
- package/src/browser.ts +7 -0
- package/src/index.ts +2 -0
- package/src/use-snap-points.ts +6 -4
- package/src/useDrawer.ts +60 -11
package/src/useDrawer.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { useControllableState } from "@
|
|
1
|
+
import { useControllableState } from "@seed-design/react-use-controllable-state";
|
|
2
|
+
import type React from "react";
|
|
2
3
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
-
import { isIOS, isMobileFirefox } from "./browser";
|
|
4
|
+
import { isAndroid, isIOS, isMobileFirefox } from "./browser";
|
|
4
5
|
import {
|
|
5
6
|
CLOSE_THRESHOLD,
|
|
6
7
|
DRAG_CLASS,
|
|
@@ -13,6 +14,21 @@ import { dampenValue, getTranslate, isInput, isVertical, reset, set } from "./he
|
|
|
13
14
|
import { usePositionFixed } from "./use-position-fixed";
|
|
14
15
|
import { useSnapPoints } from "./use-snap-points";
|
|
15
16
|
|
|
17
|
+
interface DrawerReasonToDetailMap {
|
|
18
|
+
// we might add synthetic events later if needed; currently we aim consistency; DismissableLayer gives us native events
|
|
19
|
+
closeButton: { event: MouseEvent };
|
|
20
|
+
escapeKeyDown: { event: KeyboardEvent };
|
|
21
|
+
interactOutside: { event: PointerEvent | FocusEvent };
|
|
22
|
+
drag: { event: PointerEvent };
|
|
23
|
+
handleClickOnLastSnapPoint: { event: MouseEvent };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
type DrawerChangeDetails = {
|
|
27
|
+
[R in keyof DrawerReasonToDetailMap]: {
|
|
28
|
+
reason?: R;
|
|
29
|
+
} & DrawerReasonToDetailMap[R];
|
|
30
|
+
}[keyof DrawerReasonToDetailMap];
|
|
31
|
+
|
|
16
32
|
export interface UseDrawerProps {
|
|
17
33
|
activeSnapPoint?: number | string | null;
|
|
18
34
|
setActiveSnapPoint?: (snapPoint: number | string | null) => void;
|
|
@@ -29,7 +45,7 @@ export interface UseDrawerProps {
|
|
|
29
45
|
* @default true
|
|
30
46
|
*/
|
|
31
47
|
noBodyStyles?: boolean;
|
|
32
|
-
onOpenChange?: (open: boolean) => void;
|
|
48
|
+
onOpenChange?: (open: boolean, details?: DrawerChangeDetails) => void;
|
|
33
49
|
/**
|
|
34
50
|
* Duration for which the drawer is not draggable after scrolling content inside of the drawer.
|
|
35
51
|
* @default 500ms
|
|
@@ -149,11 +165,11 @@ export function useDrawer(props: UseDrawerProps) {
|
|
|
149
165
|
closeOnEscape = true,
|
|
150
166
|
} = props;
|
|
151
167
|
|
|
152
|
-
const [isOpen = false, setIsOpen] = useControllableState({
|
|
168
|
+
const [isOpen = false, setIsOpen] = useControllableState<boolean, DrawerChangeDetails>({
|
|
153
169
|
defaultProp: defaultOpen,
|
|
154
170
|
prop: openProp,
|
|
155
|
-
onChange: (o: boolean) => {
|
|
156
|
-
onOpenChange?.(o);
|
|
171
|
+
onChange: (o: boolean, details?: DrawerChangeDetails) => {
|
|
172
|
+
onOpenChange?.(o, details);
|
|
157
173
|
|
|
158
174
|
if (!o && !nested) {
|
|
159
175
|
restorePositionSetting();
|
|
@@ -178,9 +194,15 @@ export function useDrawer(props: UseDrawerProps) {
|
|
|
178
194
|
});
|
|
179
195
|
|
|
180
196
|
const [hasBeenOpened, setHasBeenOpened] = useState<boolean>(false);
|
|
197
|
+
const [hasAnimationDone, setHasAnimationDone] = useState<boolean>(false);
|
|
181
198
|
const [isDragging, setIsDragging] = useState<boolean>(false);
|
|
182
199
|
const [shouldOverlayAnimate, setShouldOverlayAnimate] = useState<boolean>(false);
|
|
183
200
|
|
|
201
|
+
const [isCloseButtonRendered, setIsCloseButtonRendered] = useState<boolean>(false);
|
|
202
|
+
const closeButtonRef = useCallback((node: HTMLButtonElement | null) => {
|
|
203
|
+
setIsCloseButtonRendered(!!node);
|
|
204
|
+
}, []);
|
|
205
|
+
|
|
184
206
|
const overlayRef = useRef<HTMLDivElement>(null);
|
|
185
207
|
const openTime = useRef<Date | null>(null);
|
|
186
208
|
const dragStartTime = useRef<Date | null>(null);
|
|
@@ -419,12 +441,12 @@ export function useDrawer(props: UseDrawerProps) {
|
|
|
419
441
|
}, [isDragging]);
|
|
420
442
|
|
|
421
443
|
const closeDrawer = useCallback(
|
|
422
|
-
(fromWithin?: boolean) => {
|
|
444
|
+
(fromWithin?: boolean, details?: DrawerChangeDetails) => {
|
|
423
445
|
cancelDrag();
|
|
424
446
|
onClose?.();
|
|
425
447
|
|
|
426
448
|
if (!fromWithin) {
|
|
427
|
-
setIsOpen(false);
|
|
449
|
+
setIsOpen(false, details);
|
|
428
450
|
}
|
|
429
451
|
|
|
430
452
|
if (fadeFromIndex !== undefined && fadeFromIndex > 0 && activeSnapPointIndex === 0) {
|
|
@@ -489,6 +511,7 @@ export function useDrawer(props: UseDrawerProps) {
|
|
|
489
511
|
closeDrawer,
|
|
490
512
|
velocity,
|
|
491
513
|
dismissible,
|
|
514
|
+
event: event.nativeEvent,
|
|
492
515
|
});
|
|
493
516
|
onReleaseProp?.(event, true);
|
|
494
517
|
return;
|
|
@@ -501,7 +524,7 @@ export function useDrawer(props: UseDrawerProps) {
|
|
|
501
524
|
}
|
|
502
525
|
|
|
503
526
|
if (velocity > VELOCITY_THRESHOLD) {
|
|
504
|
-
closeDrawer();
|
|
527
|
+
closeDrawer(false, { reason: "drag", event: event.nativeEvent });
|
|
505
528
|
onReleaseProp?.(event, false);
|
|
506
529
|
return;
|
|
507
530
|
}
|
|
@@ -520,7 +543,7 @@ export function useDrawer(props: UseDrawerProps) {
|
|
|
520
543
|
Math.abs(swipeAmount) >=
|
|
521
544
|
(isHorizontalSwipe ? visibleDrawerWidth : visibleDrawerHeight) * closeThreshold
|
|
522
545
|
) {
|
|
523
|
-
closeDrawer();
|
|
546
|
+
closeDrawer(false, { reason: "drag", event: event.nativeEvent });
|
|
524
547
|
onReleaseProp?.(event, false);
|
|
525
548
|
return;
|
|
526
549
|
}
|
|
@@ -583,7 +606,7 @@ export function useDrawer(props: UseDrawerProps) {
|
|
|
583
606
|
} else {
|
|
584
607
|
drawerRef.current.style.height = `${Math.max(newDrawerHeight, visualViewportHeight - offsetFromTop)}px`;
|
|
585
608
|
}
|
|
586
|
-
} else if (!isMobileFirefox()) {
|
|
609
|
+
} else if (!isMobileFirefox() && !isAndroid()) {
|
|
587
610
|
drawerRef.current.style.height = `${initialDrawerHeight.current}px`;
|
|
588
611
|
}
|
|
589
612
|
|
|
@@ -607,12 +630,32 @@ export function useDrawer(props: UseDrawerProps) {
|
|
|
607
630
|
}
|
|
608
631
|
}, [modal]);
|
|
609
632
|
|
|
633
|
+
// Effect 1: Track drawer open state
|
|
610
634
|
useEffect(() => {
|
|
611
635
|
if (isOpen) {
|
|
612
636
|
setHasBeenOpened(true);
|
|
613
637
|
}
|
|
614
638
|
}, [isOpen]);
|
|
615
639
|
|
|
640
|
+
// Effect 2: Handle animation state and timer
|
|
641
|
+
useEffect(() => {
|
|
642
|
+
if (isOpen) {
|
|
643
|
+
// Only reset animation state if this is the first open
|
|
644
|
+
if (!hasBeenOpened) {
|
|
645
|
+
setHasAnimationDone(false);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
const timeoutId = setTimeout(() => {
|
|
649
|
+
setHasAnimationDone(true);
|
|
650
|
+
}, TRANSITIONS.ENTER_DURATION * 1000);
|
|
651
|
+
|
|
652
|
+
return () => clearTimeout(timeoutId);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// Reset animation state when drawer closes
|
|
656
|
+
setHasAnimationDone(false);
|
|
657
|
+
}, [isOpen, hasBeenOpened]);
|
|
658
|
+
|
|
616
659
|
useEffect(() => {
|
|
617
660
|
if (isOpen && snapPoints && fadeFromIndex === 0) {
|
|
618
661
|
setShouldOverlayAnimate(true);
|
|
@@ -657,6 +700,9 @@ export function useDrawer(props: UseDrawerProps) {
|
|
|
657
700
|
setIsOpen,
|
|
658
701
|
closeOnInteractOutside,
|
|
659
702
|
closeOnEscape,
|
|
703
|
+
hasAnimationDone,
|
|
704
|
+
closeButtonRef,
|
|
705
|
+
isCloseButtonRendered,
|
|
660
706
|
}),
|
|
661
707
|
[
|
|
662
708
|
activeSnapPoint,
|
|
@@ -683,6 +729,9 @@ export function useDrawer(props: UseDrawerProps) {
|
|
|
683
729
|
onRelease,
|
|
684
730
|
onDrag,
|
|
685
731
|
onPress,
|
|
732
|
+
hasAnimationDone,
|
|
733
|
+
closeButtonRef,
|
|
734
|
+
isCloseButtonRendered,
|
|
686
735
|
],
|
|
687
736
|
);
|
|
688
737
|
}
|