@lodev09/react-native-true-sheet 3.11.3 → 3.11.5
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/RNTrueSheet.podspec +6 -2
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerView.kt +69 -1
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentView.kt +62 -4
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetPackage.kt +2 -1
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetPeekView.kt +72 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetPeekViewManager.kt +33 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +7 -1
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +10 -0
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDetentCalculator.kt +24 -1
- package/ios/TrueSheetContainerView.h +18 -0
- package/ios/TrueSheetContainerView.mm +78 -1
- package/ios/TrueSheetContentView.mm +82 -4
- package/ios/TrueSheetPeekView.h +32 -0
- package/ios/TrueSheetPeekView.mm +99 -0
- package/ios/TrueSheetView.mm +19 -0
- package/ios/TrueSheetViewController.h +2 -0
- package/ios/TrueSheetViewController.mm +10 -0
- package/ios/core/TrueSheetDetentCalculator.h +10 -0
- package/ios/core/TrueSheetDetentCalculator.mm +9 -0
- package/ios/tvos/TrueSheetStubs.mm +152 -0
- package/lib/module/TrueSheet.js +2 -1
- package/lib/module/TrueSheet.js.map +1 -1
- package/lib/module/TrueSheet.web.js +104 -69
- package/lib/module/TrueSheet.web.js.map +1 -1
- package/lib/module/TrueSheetPeek.js +15 -0
- package/lib/module/TrueSheetPeek.js.map +1 -0
- package/lib/module/TrueSheetPeek.web.js +46 -0
- package/lib/module/TrueSheetPeek.web.js.map +1 -0
- package/lib/module/fabric/TrueSheetPeekViewNativeComponent.ts +8 -0
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/mocks/index.js +10 -0
- package/lib/module/mocks/index.js.map +1 -1
- package/lib/module/web/vaul/constants.js +1 -0
- package/lib/module/web/vaul/constants.js.map +1 -1
- package/lib/module/web/vaul/index.js +2 -0
- package/lib/module/web/vaul/index.js.map +1 -1
- package/lib/module/web/vaul/use-snap-points.js +6 -4
- package/lib/module/web/vaul/use-snap-points.js.map +1 -1
- package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheet.types.d.ts +10 -0
- package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheet.web.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheetPeek.d.ts +9 -0
- package/lib/typescript/src/TrueSheetPeek.d.ts.map +1 -0
- package/lib/typescript/src/TrueSheetPeek.web.d.ts +19 -0
- package/lib/typescript/src/TrueSheetPeek.web.d.ts.map +1 -0
- package/lib/typescript/src/fabric/TrueSheetPeekViewNativeComponent.d.ts +6 -0
- package/lib/typescript/src/fabric/TrueSheetPeekViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +1 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/mocks/index.d.ts +6 -2
- package/lib/typescript/src/mocks/index.d.ts.map +1 -1
- package/lib/typescript/src/web/vaul/constants.d.ts +1 -0
- package/lib/typescript/src/web/vaul/constants.d.ts.map +1 -1
- package/lib/typescript/src/web/vaul/index.d.ts +6 -1
- package/lib/typescript/src/web/vaul/index.d.ts.map +1 -1
- package/lib/typescript/src/web/vaul/use-snap-points.d.ts +2 -1
- package/lib/typescript/src/web/vaul/use-snap-points.d.ts.map +1 -1
- package/package.json +4 -1
- package/src/TrueSheet.tsx +2 -1
- package/src/TrueSheet.types.ts +11 -0
- package/src/TrueSheet.web.tsx +110 -71
- package/src/TrueSheetPeek.tsx +11 -0
- package/src/TrueSheetPeek.web.tsx +48 -0
- package/src/fabric/TrueSheetPeekViewNativeComponent.ts +8 -0
- package/src/index.ts +1 -0
- package/src/mocks/index.ts +8 -1
- package/src/web/vaul/constants.ts +2 -0
- package/src/web/vaul/index.tsx +7 -0
- package/src/web/vaul/use-snap-points.ts +17 -4
package/src/TrueSheet.types.ts
CHANGED
|
@@ -224,6 +224,17 @@ export type SheetDetent =
|
|
|
224
224
|
*/
|
|
225
225
|
| 'auto'
|
|
226
226
|
|
|
227
|
+
/**
|
|
228
|
+
* Collapsed height based on the combined `header` and `footer` heights.
|
|
229
|
+
* Render a `TrueSheetPeek` component within the content to also include
|
|
230
|
+
* the content up to its bottom edge.
|
|
231
|
+
* Falls back to a fixed height of `150` when none is provided.
|
|
232
|
+
*
|
|
233
|
+
* @platform android
|
|
234
|
+
* @platform ios 16+
|
|
235
|
+
*/
|
|
236
|
+
| 'peek'
|
|
237
|
+
|
|
227
238
|
/**
|
|
228
239
|
* Relative height as a fraction (0-1) of the available height.
|
|
229
240
|
* For example, 0.5 represents 50% of the available height.
|
package/src/TrueSheet.web.tsx
CHANGED
|
@@ -11,9 +11,11 @@ import {
|
|
|
11
11
|
useState,
|
|
12
12
|
} from 'react';
|
|
13
13
|
import { View, useColorScheme, useWindowDimensions } from 'react-native';
|
|
14
|
+
import type { LayoutChangeEvent } from 'react-native';
|
|
14
15
|
|
|
15
16
|
import { Drawer } from './web/vaul';
|
|
16
|
-
import { TRANSITIONS } from './web/vaul/constants';
|
|
17
|
+
import { DEFAULT_PEEK_HEIGHT, TRANSITIONS } from './web/vaul/constants';
|
|
18
|
+
import { TrueSheetPeekContext } from './TrueSheetPeek.web';
|
|
17
19
|
import type {
|
|
18
20
|
DetentChangeEvent,
|
|
19
21
|
DetentInfoEventPayload,
|
|
@@ -99,7 +101,10 @@ const TrueSheetComponent = forwardRef<TrueSheetMethods, TrueSheetProps>((props,
|
|
|
99
101
|
} = props;
|
|
100
102
|
|
|
101
103
|
const validDetents = useMemo(
|
|
102
|
-
() =>
|
|
104
|
+
() =>
|
|
105
|
+
detents.filter(
|
|
106
|
+
(d): d is SheetDetent => typeof d === 'number' || d === 'auto' || d === 'peek'
|
|
107
|
+
),
|
|
103
108
|
[detents]
|
|
104
109
|
);
|
|
105
110
|
|
|
@@ -149,7 +154,7 @@ const TrueSheetComponent = forwardRef<TrueSheetMethods, TrueSheetProps>((props,
|
|
|
149
154
|
setActiveSnapPoint(
|
|
150
155
|
snapPoint == null
|
|
151
156
|
? null
|
|
152
|
-
: typeof snapPoint === 'number' || snapPoint === 'auto'
|
|
157
|
+
: typeof snapPoint === 'number' || snapPoint === 'auto' || snapPoint === 'peek'
|
|
153
158
|
? (snapPoint as SheetDetent)
|
|
154
159
|
: null
|
|
155
160
|
);
|
|
@@ -227,6 +232,29 @@ const TrueSheetComponent = forwardRef<TrueSheetMethods, TrueSheetProps>((props,
|
|
|
227
232
|
|
|
228
233
|
const drawerContentRef = useRef<HTMLDivElement | null>(null);
|
|
229
234
|
|
|
235
|
+
// Measured header/footer heights drive the 'peek' snap point — mirrors
|
|
236
|
+
// native, where the controller tracks headerHeight/footerHeight.
|
|
237
|
+
const [headerHeight, setHeaderHeight] = useState(0);
|
|
238
|
+
const [footerHeight, setFooterHeight] = useState(0);
|
|
239
|
+
|
|
240
|
+
const handleHeaderLayout = useCallback((e: LayoutChangeEvent) => {
|
|
241
|
+
setHeaderHeight(e.nativeEvent.layout.height);
|
|
242
|
+
}, []);
|
|
243
|
+
|
|
244
|
+
const handleFooterLayout = useCallback((e: LayoutChangeEvent) => {
|
|
245
|
+
setFooterHeight(e.nativeEvent.layout.height);
|
|
246
|
+
}, []);
|
|
247
|
+
|
|
248
|
+
// Distance from the content top to the bottom of a `TrueSheetPeek` rendered
|
|
249
|
+
// within the content — measured by the peek against `contentRef`.
|
|
250
|
+
const [peekContentHeight, setPeekContentHeight] = useState(0);
|
|
251
|
+
const contentRef = useRef<View>(null);
|
|
252
|
+
const peekContext = useMemo(() => ({ contentRef, setPeekContentHeight }), []);
|
|
253
|
+
|
|
254
|
+
const peekHeight =
|
|
255
|
+
(header ? headerHeight : 0) + (footer ? footerHeight : 0) + peekContentHeight ||
|
|
256
|
+
DEFAULT_PEEK_HEIGHT;
|
|
257
|
+
|
|
230
258
|
// Present/dismiss events. The sheet settles via a CSS `transform` transition
|
|
231
259
|
// on either the drawer (snap-points on autopresent) or the wrapper (whole-
|
|
232
260
|
// card slide on reopen/dismiss). `Animation.finished` from the Web Animations
|
|
@@ -295,6 +323,10 @@ const TrueSheetComponent = forwardRef<TrueSheetMethods, TrueSheetProps>((props,
|
|
|
295
323
|
const h = Math.min(d * effectiveH, ceiling);
|
|
296
324
|
positions.push(effectiveH - h);
|
|
297
325
|
values.push(effectiveH > 0 ? h / effectiveH : 0);
|
|
326
|
+
} else if (d === 'peek') {
|
|
327
|
+
const h = Math.min(peekHeight, ceiling);
|
|
328
|
+
positions.push(effectiveH - h);
|
|
329
|
+
values.push(effectiveH > 0 ? h / effectiveH : 0);
|
|
298
330
|
} else {
|
|
299
331
|
positions.push(effectiveH - autoHeight);
|
|
300
332
|
values.push(effectiveH > 0 ? autoHeight / effectiveH : 0);
|
|
@@ -346,7 +378,7 @@ const TrueSheetComponent = forwardRef<TrueSheetMethods, TrueSheetProps>((props,
|
|
|
346
378
|
|
|
347
379
|
return { index: count - 1, detent: values[count - 1]! };
|
|
348
380
|
},
|
|
349
|
-
[effectiveDetached, detachedOffset, maxContentHeight]
|
|
381
|
+
[effectiveDetached, detachedOffset, maxContentHeight, peekHeight]
|
|
350
382
|
);
|
|
351
383
|
|
|
352
384
|
const handlePositionChange = useCallback(
|
|
@@ -844,75 +876,82 @@ const TrueSheetComponent = forwardRef<TrueSheetMethods, TrueSheetProps>((props,
|
|
|
844
876
|
);
|
|
845
877
|
|
|
846
878
|
return (
|
|
847
|
-
<
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
<Drawer.
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
879
|
+
<TrueSheetPeekContext.Provider value={peekContext}>
|
|
880
|
+
<Drawer.Root
|
|
881
|
+
open={isOpen}
|
|
882
|
+
onOpenChange={handleOpenChange}
|
|
883
|
+
onPositionChange={handlePositionChange}
|
|
884
|
+
onDrag={handleDrag}
|
|
885
|
+
onRelease={handleRelease}
|
|
886
|
+
dismissible={dismissible}
|
|
887
|
+
draggable={draggable}
|
|
888
|
+
repositionInputs={false}
|
|
889
|
+
modal={dimmed}
|
|
890
|
+
nested={isNested}
|
|
891
|
+
detached={effectiveDetached}
|
|
892
|
+
detachedOffset={effectiveDetachedOffset}
|
|
893
|
+
detachedRadius={effectiveCornerRadius}
|
|
894
|
+
maxContentHeight={effectiveMaxContentHeight}
|
|
895
|
+
peekHeight={peekHeight}
|
|
896
|
+
initialAnimated={initialDetentAnimated}
|
|
897
|
+
detachedWrapperStyle={wrapperStyle}
|
|
898
|
+
onContentHeightChange={setMeasuredContentHeight}
|
|
899
|
+
activeSnapPoint={activeSnapPoint}
|
|
900
|
+
setActiveSnapPoint={handleSetActiveSnapPoint}
|
|
901
|
+
{...snapPointsProps}
|
|
902
|
+
>
|
|
903
|
+
<Drawer.Portal container={portalContainer ?? undefined}>
|
|
904
|
+
<Drawer.Overlay style={overlayStyle} />
|
|
905
|
+
<Drawer.Content
|
|
906
|
+
ref={drawerContentRef}
|
|
907
|
+
style={mergedContentStyle}
|
|
908
|
+
onPointerDownOutside={handlePointerDownOutside}
|
|
909
|
+
detachedSiblings={
|
|
910
|
+
footer ? (
|
|
911
|
+
<div style={footerFloatStyle}>
|
|
912
|
+
<View style={footerStyle} onLayout={handleFooterLayout}>
|
|
913
|
+
{isValidElement(footer) ? footer : createElement(footer)}
|
|
914
|
+
</View>
|
|
915
|
+
</div>
|
|
916
|
+
) : undefined
|
|
917
|
+
}
|
|
918
|
+
>
|
|
919
|
+
<Drawer.Title style={visuallyHiddenStyle}>Sheet</Drawer.Title>
|
|
920
|
+
{grabber && <Drawer.Handle style={handleStyle} />}
|
|
921
|
+
{scrollable ? (
|
|
922
|
+
// vaul wraps children in `[data-vaul-auto-size-wrapper]` (display:
|
|
923
|
+
// flow-root) which doesn't honor descendant flex layout. Use an
|
|
924
|
+
// absolute fill sized to the visible portion (via vaul's
|
|
925
|
+
// `--snap-point-height` var) so the inner flex column has a
|
|
926
|
+
// definite height for the scroll container's flex:1 to fill.
|
|
927
|
+
<div style={scrollableLayoutStyle}>
|
|
928
|
+
{header && (
|
|
929
|
+
<View style={headerStyle} onLayout={handleHeaderLayout}>
|
|
930
|
+
{isValidElement(header) ? header : createElement(header)}
|
|
931
|
+
</View>
|
|
932
|
+
)}
|
|
933
|
+
<div style={scrollableContainerStyle}>
|
|
934
|
+
<View ref={contentRef} style={style}>
|
|
935
|
+
{children}
|
|
936
|
+
</View>
|
|
937
|
+
</div>
|
|
901
938
|
</div>
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
939
|
+
) : (
|
|
940
|
+
<>
|
|
941
|
+
{header && (
|
|
942
|
+
<View style={headerStyle} onLayout={handleHeaderLayout}>
|
|
943
|
+
{isValidElement(header) ? header : createElement(header)}
|
|
944
|
+
</View>
|
|
945
|
+
)}
|
|
946
|
+
<View ref={contentRef} style={style}>
|
|
947
|
+
{children}
|
|
908
948
|
</View>
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
</Drawer.Root>
|
|
949
|
+
</>
|
|
950
|
+
)}
|
|
951
|
+
</Drawer.Content>
|
|
952
|
+
</Drawer.Portal>
|
|
953
|
+
</Drawer.Root>
|
|
954
|
+
</TrueSheetPeekContext.Provider>
|
|
916
955
|
);
|
|
917
956
|
});
|
|
918
957
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ViewProps } from 'react-native';
|
|
2
|
+
|
|
3
|
+
import TrueSheetPeekViewNativeComponent from './fabric/TrueSheetPeekViewNativeComponent';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Wrapper component that marks its children as the sheet's peek content.
|
|
7
|
+
* When rendered within a `TrueSheet`, the `"peek"` detent reveals everything
|
|
8
|
+
* from the top of the sheet through the bottom of this component — content
|
|
9
|
+
* below it stays hidden until the sheet is expanded.
|
|
10
|
+
*/
|
|
11
|
+
export const TrueSheetPeek = (props: ViewProps) => <TrueSheetPeekViewNativeComponent {...props} />;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { createContext, useContext, useEffect, useRef, type RefObject } from 'react';
|
|
2
|
+
import { View, type LayoutChangeEvent, type ViewProps } from 'react-native';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Reports the measured peek content height to the owning TrueSheet.
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export interface TrueSheetPeekContextValue {
|
|
9
|
+
contentRef: RefObject<View | null>;
|
|
10
|
+
setPeekContentHeight: (height: number) => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const TrueSheetPeekContext = createContext<TrueSheetPeekContextValue | null>(null);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Wrapper component that marks its children as the sheet's peek content.
|
|
17
|
+
* When rendered within a `TrueSheet`, the `"peek"` detent reveals everything
|
|
18
|
+
* from the top of the sheet through the bottom of this component — content
|
|
19
|
+
* below it stays hidden until the sheet is expanded.
|
|
20
|
+
*/
|
|
21
|
+
export const TrueSheetPeek = ({ onLayout, ...rest }: ViewProps) => {
|
|
22
|
+
const context = useContext(TrueSheetPeekContext);
|
|
23
|
+
const viewRef = useRef<View>(null);
|
|
24
|
+
|
|
25
|
+
useEffect(() => () => context?.setPeekContentHeight(0), [context]);
|
|
26
|
+
|
|
27
|
+
const handleLayout = (event: LayoutChangeEvent) => {
|
|
28
|
+
if (context) {
|
|
29
|
+
// On web, View refs resolve to the underlying DOM elements.
|
|
30
|
+
const peekElement = viewRef.current as unknown as HTMLElement | null;
|
|
31
|
+
const contentElement = context.contentRef.current as unknown as HTMLElement | null;
|
|
32
|
+
|
|
33
|
+
// Distance from the top of the content view to the bottom of the peek view,
|
|
34
|
+
// so the peek view's offset within the content (padding, views above it)
|
|
35
|
+
// counts toward the peek detent.
|
|
36
|
+
const bottom =
|
|
37
|
+
peekElement && contentElement
|
|
38
|
+
? peekElement.getBoundingClientRect().bottom - contentElement.getBoundingClientRect().top
|
|
39
|
+
: event.nativeEvent.layout.height;
|
|
40
|
+
|
|
41
|
+
context.setPeekContentHeight(bottom);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
onLayout?.(event);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
return <View {...rest} ref={viewRef} onLayout={handleLayout} />;
|
|
48
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ViewProps } from 'react-native';
|
|
2
|
+
import { codegenNativeComponent } from 'react-native';
|
|
3
|
+
|
|
4
|
+
export interface NativeProps extends ViewProps {
|
|
5
|
+
// Peek-specific props can be added here if needed
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default codegenNativeComponent<NativeProps>('TrueSheetPeekView', {});
|
package/src/index.ts
CHANGED
package/src/mocks/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { createElement, isValidElement, type ReactNode } from 'react';
|
|
2
|
-
import { View } from 'react-native';
|
|
2
|
+
import { View, type ViewProps } from 'react-native';
|
|
3
3
|
|
|
4
4
|
import type { TrueSheetProps, TrueSheetStaticMethods } from '../TrueSheet.types';
|
|
5
5
|
|
|
@@ -59,6 +59,13 @@ export class TrueSheet extends React.Component<TrueSheetProps, TrueSheetState> {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Mock TrueSheetPeek component for testing.
|
|
64
|
+
*/
|
|
65
|
+
export function TrueSheetPeek({ children, ...rest }: ViewProps) {
|
|
66
|
+
return React.createElement(View, rest, children);
|
|
67
|
+
}
|
|
68
|
+
|
|
62
69
|
/**
|
|
63
70
|
* Mock TrueSheetProvider for testing.
|
|
64
71
|
*/
|
package/src/web/vaul/index.tsx
CHANGED
|
@@ -181,6 +181,11 @@ export type DialogProps = {
|
|
|
181
181
|
* respect a user-specified ceiling.
|
|
182
182
|
*/
|
|
183
183
|
maxContentHeight?: number;
|
|
184
|
+
/**
|
|
185
|
+
* Resolved height (in px) for the 'peek' snap point — the caller measures
|
|
186
|
+
* its header/footer and passes the combined height.
|
|
187
|
+
*/
|
|
188
|
+
peekHeight?: number;
|
|
184
189
|
/**
|
|
185
190
|
* When `false` the first snap on mount is applied without a transition so
|
|
186
191
|
* the sheet appears at its target detent instantly. Defaults to `true`.
|
|
@@ -231,6 +236,7 @@ export function Root({
|
|
|
231
236
|
detachedRadius = 0,
|
|
232
237
|
detachedWrapperStyle,
|
|
233
238
|
maxContentHeight,
|
|
239
|
+
peekHeight,
|
|
234
240
|
initialAnimated = true,
|
|
235
241
|
onContentHeightChange,
|
|
236
242
|
}: DialogProps) {
|
|
@@ -307,6 +313,7 @@ export function Root({
|
|
|
307
313
|
contentHeight,
|
|
308
314
|
detachedOffset: detached ? detachedOffset : 0,
|
|
309
315
|
maxContentHeight,
|
|
316
|
+
peekHeight,
|
|
310
317
|
initialAnimated,
|
|
311
318
|
});
|
|
312
319
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @ts-nocheck — vendored upstream, incompatible with noUncheckedIndexedAccess
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { set, isVertical } from './helpers';
|
|
4
|
-
import { TRANSITIONS, VELOCITY_THRESHOLD } from './constants';
|
|
4
|
+
import { DEFAULT_PEEK_HEIGHT, TRANSITIONS, VELOCITY_THRESHOLD } from './constants';
|
|
5
5
|
import { useControllableState } from './use-controllable-state';
|
|
6
6
|
import type { DrawerDirection } from './types';
|
|
7
7
|
|
|
@@ -20,6 +20,7 @@ export function useSnapPoints({
|
|
|
20
20
|
contentHeight,
|
|
21
21
|
detachedOffset = 0,
|
|
22
22
|
maxContentHeight,
|
|
23
|
+
peekHeight,
|
|
23
24
|
initialAnimated = true,
|
|
24
25
|
}: {
|
|
25
26
|
activeSnapPointProp?: number | string | null;
|
|
@@ -36,6 +37,7 @@ export function useSnapPoints({
|
|
|
36
37
|
contentHeight?: number;
|
|
37
38
|
detachedOffset?: number;
|
|
38
39
|
maxContentHeight?: number;
|
|
40
|
+
peekHeight?: number;
|
|
39
41
|
initialAnimated?: boolean;
|
|
40
42
|
}) {
|
|
41
43
|
const [activeSnapPoint, setActiveSnapPoint] = useControllableState<string | number | null>({
|
|
@@ -102,11 +104,14 @@ export function useSnapPoints({
|
|
|
102
104
|
snapPoints?.map((snapPoint) => {
|
|
103
105
|
// 'auto' resolves to measured content height. Falls back to half the
|
|
104
106
|
// container so the initial snap is close to final before ResizeObserver
|
|
105
|
-
// reports a real measurement.
|
|
107
|
+
// reports a real measurement. 'peek' resolves to the caller-measured
|
|
108
|
+
// header + footer height.
|
|
106
109
|
const resolved =
|
|
107
110
|
snapPoint === 'auto'
|
|
108
111
|
? `${contentHeight && contentHeight > 0 ? contentHeight : effectiveHeight / 2}px`
|
|
109
|
-
: snapPoint
|
|
112
|
+
: snapPoint === 'peek'
|
|
113
|
+
? `${peekHeight && peekHeight > 0 ? peekHeight : DEFAULT_PEEK_HEIGHT}px`
|
|
114
|
+
: snapPoint;
|
|
110
115
|
const isPx = typeof resolved === 'string';
|
|
111
116
|
let snapPointAsNumber = 0;
|
|
112
117
|
|
|
@@ -151,7 +156,15 @@ export function useSnapPoints({
|
|
|
151
156
|
return width;
|
|
152
157
|
}) ?? []
|
|
153
158
|
);
|
|
154
|
-
}, [
|
|
159
|
+
}, [
|
|
160
|
+
snapPoints,
|
|
161
|
+
windowDimensions,
|
|
162
|
+
container,
|
|
163
|
+
contentHeight,
|
|
164
|
+
detachedOffset,
|
|
165
|
+
maxContentHeight,
|
|
166
|
+
peekHeight,
|
|
167
|
+
]);
|
|
155
168
|
|
|
156
169
|
const activeSnapPointOffset = React.useMemo(
|
|
157
170
|
() => (activeSnapPointIndex !== null ? snapPointsOffset?.[activeSnapPointIndex] : null),
|