Skip to content

Commit bc0ca47

Browse files
committed
chore: update podfile
1 parent b1d0f27 commit bc0ca47

3 files changed

Lines changed: 81 additions & 8 deletions

File tree

example/bare/ios/Podfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2777,7 +2777,7 @@ PODS:
27772777
- ReactCommon/turbomodule/core
27782778
- SocketRocket
27792779
- Yoga
2780-
- RNTrueSheet (3.10.0):
2780+
- RNTrueSheet (3.11.0-beta.7):
27812781
- boost
27822782
- DoubleConversion
27832783
- fast_float
@@ -3248,7 +3248,7 @@ SPEC CHECKSUMS:
32483248
RNGestureHandler: b407c25a3f51d22dd7430e6b530f753f112b7e77
32493249
RNReanimated: 292cd58688552a22b3fc1cefcfbc49b336dfed68
32503250
RNScreens: afaf526a9c804c3b4503f950cf3e67ed81e29ada
3251-
RNTrueSheet: 819132cbb5713a5794cc0574c4d5fa7859a7c7de
3251+
RNTrueSheet: eca911005316e6b28240ea15132c8f768517a0c1
32523252
RNWorklets: 01efdd402d236a13651ea5ea5437ca85a44e7afa
32533253
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
32543254
Yoga: b669e79fa0f8d3f6f5e35372345f54b99e06b13c

src/TrueSheet.web.tsx

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,8 @@ const TrueSheetComponent = forwardRef<TrueSheetMethods, TrueSheetProps>((props,
482482
const { isNested, dismissAbove, descendants } = useSheetStack(
483483
methodsRef,
484484
drawerContentRef,
485-
isOpen
485+
isOpen,
486+
isLandscapeOrTablet && presentation === 'form'
486487
);
487488
dismissAboveRef.current = dismissAbove;
488489

@@ -492,12 +493,18 @@ const TrueSheetComponent = forwardRef<TrueSheetMethods, TrueSheetProps>((props,
492493
useEffect(() => {
493494
const parent = drawerContentRef.current;
494495
if (!parent) return;
496+
const parentWrapper = parent.closest<HTMLElement>('[data-vaul-detached-wrapper]');
495497

496498
const transition = `transform ${TRANSITIONS.DURATION}s cubic-bezier(${TRANSITIONS.EASE.join(',')})`;
499+
const wrapperTransition = `clip-path ${TRANSITIONS.DURATION}s cubic-bezier(${TRANSITIONS.EASE.join(',')})`;
497500

498501
if (descendants.length === 0) {
499502
parent.style.transition = transition;
500503
parent.style.transform = '';
504+
if (parentWrapper && parentWrapper.style.clipPath) {
505+
parentWrapper.style.transition = wrapperTransition;
506+
parentWrapper.style.clipPath = 'inset(0px round 0px)';
507+
}
501508
return;
502509
}
503510

@@ -513,13 +520,67 @@ const TrueSheetComponent = forwardRef<TrueSheetMethods, TrueSheetProps>((props,
513520
return targetY;
514521
};
515522

523+
// When a form-sheet descendant is present, clip the parent to the form
524+
// card's viewport box so the parts that would peek above/around the card
525+
// are hidden. Form-card box is derived from the child's inline styles
526+
// (vs. getBoundingClientRect) so it's the at-rest box, not skewed by
527+
// vaul's wrapper slide-in. Insets are relative to the parent wrapper's
528+
// rect — the parent wrapper isn't necessarily viewport-sized (e.g., it
529+
// has DEFAULT_MAX_WIDTH on tablet/landscape).
530+
// Clip-path transitions with the same duration/easing as the cascade
531+
// transform so the visible box and the drawer's content slide together;
532+
// otherwise the content animates against a static wrapper boundary.
533+
// We seed clip-path from `inset(0)` (= no clip) before setting the target
534+
// inset so the browser interpolates between two inset() shapes — going
535+
// from `none` directly to inset() is interpolated inconsistently.
536+
const applyFormClip = () => {
537+
if (!parentWrapper) return;
538+
const form = descendants.find((d) => d.isFormSheetRef.current);
539+
if (!form) {
540+
if (parentWrapper.style.clipPath) {
541+
parentWrapper.style.transition = wrapperTransition;
542+
parentWrapper.style.clipPath = 'inset(0px round 0px)';
543+
}
544+
return;
545+
}
546+
const childDrawer = form.nodeRef.current;
547+
const childWrapper = childDrawer?.closest<HTMLElement>('[data-vaul-detached-wrapper]');
548+
if (!childDrawer || !childWrapper) return;
549+
const snapY = parseFloat(childDrawer.style.getPropertyValue('--snap-point-height')) || 0;
550+
const childBottomGap = parseFloat(childWrapper.style.bottom) || 0;
551+
const childMaxW =
552+
parseFloat(childWrapper.style.maxWidth) || window.innerWidth;
553+
const formLeft = (window.innerWidth - childMaxW) / 2;
554+
const formRight = (window.innerWidth + childMaxW) / 2;
555+
const formBottom = window.innerHeight - childBottomGap;
556+
const rect = parentWrapper.getBoundingClientRect();
557+
const top = Math.max(0, snapY - rect.top);
558+
const left = Math.max(0, formLeft - rect.left);
559+
const right = Math.max(0, rect.right - formRight);
560+
const bottom = Math.max(0, rect.bottom - formBottom);
561+
// Seed inset(0 round 0) so the first transition interpolates between
562+
// two inset() shapes with matching `round` values (a missing `round`
563+
// would interpolate inconsistently).
564+
if (!parentWrapper.style.clipPath) {
565+
parentWrapper.style.transition = '';
566+
parentWrapper.style.clipPath = 'inset(0px round 0px)';
567+
// eslint-disable-next-line no-void
568+
void parentWrapper.offsetHeight;
569+
}
570+
parentWrapper.style.transition = wrapperTransition;
571+
const radius = cornerRadius ?? DEFAULT_CORNER_RADIUS;
572+
parentWrapper.style.clipPath = `inset(${top}px ${right}px ${bottom}px ${left}px round ${radius}px)`;
573+
};
574+
516575
const apply = () => {
517576
const targetY = computeTargetY();
518577
const match = parent.style.transform.match(/translate3d\([^,]*,\s*(-?\d*\.?\d+)px/);
519578
const currentY = match ? parseFloat(match[1]!) : 0;
520-
if (Math.abs(currentY - targetY) < 0.5) return;
521-
parent.style.transition = transition;
522-
parent.style.transform = `translate3d(0, ${targetY}px, 0)`;
579+
if (Math.abs(currentY - targetY) >= 0.5) {
580+
parent.style.transition = transition;
581+
parent.style.transform = `translate3d(0, ${targetY}px, 0)`;
582+
}
583+
applyFormClip();
523584
};
524585

525586
const raf = requestAnimationFrame(apply);

src/TrueSheetProvider.web.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ type NodeRef = RefObject<HTMLDivElement | null>;
1919
interface StackEntry {
2020
ref: SheetRef;
2121
nodeRef: NodeRef;
22+
isFormSheetRef: RefObject<boolean>;
2223
}
2324

2425
interface SheetContextValue {
@@ -166,10 +167,21 @@ export function useRegisterSheet(name: string | undefined, ref: SheetRef): void
166167
* Registers the sheet in the open stack while `isOpen` is true and returns
167168
* live data used by each sheet to render stacked visuals and dismiss children.
168169
*/
169-
export function useSheetStack(ref: SheetRef, nodeRef: NodeRef, isOpen: boolean) {
170+
export function useSheetStack(
171+
ref: SheetRef,
172+
nodeRef: NodeRef,
173+
isOpen: boolean,
174+
isFormSheet: boolean
175+
) {
170176
const ctx = useContext(SheetContext);
171177

172-
const entry = useMemo<StackEntry>(() => ({ ref, nodeRef }), [ref, nodeRef]);
178+
const isFormSheetRef = useRef(isFormSheet);
179+
isFormSheetRef.current = isFormSheet;
180+
181+
const entry = useMemo<StackEntry>(
182+
() => ({ ref, nodeRef, isFormSheetRef }),
183+
[ref, nodeRef]
184+
);
173185

174186
useEffect(() => {
175187
if (!ctx || !isOpen) return;

0 commit comments

Comments
 (0)