@tamagui/sheet 1.0.1-beta.174 → 1.0.1-beta.176
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/dist/cjs/Sheet.js +30 -6
- package/dist/cjs/Sheet.js.map +2 -2
- package/dist/cjs/SheetScrollView.js.map +2 -2
- package/dist/esm/Sheet.js +31 -6
- package/dist/esm/Sheet.js.map +2 -2
- package/dist/esm/SheetScrollView.js.map +2 -2
- package/dist/jsx/Sheet.js +28 -6
- package/dist/jsx/Sheet.js.map +2 -2
- package/dist/jsx/SheetScrollView.js.map +2 -2
- package/package.json +10 -10
- package/src/Sheet.tsx +39 -5
- package/src/SheetScrollView.tsx +2 -5
package/dist/cjs/Sheet.js
CHANGED
|
@@ -383,8 +383,9 @@ const Sheet = (0, import_core.withStaticProperties)(
|
|
|
383
383
|
onMoveShouldSetPanResponder: onMoveShouldSet,
|
|
384
384
|
onPanResponderGrant: grant,
|
|
385
385
|
onPanResponderMove: (_e, { dy }) => {
|
|
386
|
-
const
|
|
387
|
-
|
|
386
|
+
const toFull = dy + startY;
|
|
387
|
+
const to = resisted(toFull, minY);
|
|
388
|
+
animatedNumber.setValue(to, { type: "direct" });
|
|
388
389
|
},
|
|
389
390
|
onPanResponderEnd: finish,
|
|
390
391
|
onPanResponderTerminate: finish,
|
|
@@ -425,6 +426,20 @@ const Sheet = (0, import_core.withStaticProperties)(
|
|
|
425
426
|
return null;
|
|
426
427
|
}
|
|
427
428
|
const AnimatedView = driver["NumberView"] ?? driver.View;
|
|
429
|
+
const [isShowingInnerSheet, setIsShowingInnerSheet] = (0, import_react.useState)(false);
|
|
430
|
+
const shouldHideParentSheet = !import_core.isWeb && modal && isShowingInnerSheet;
|
|
431
|
+
const parentSheetContext = (0, import_react.useContext)(SheetInsideSheetContext);
|
|
432
|
+
const onInnerSheet = (0, import_react.useCallback)((hasChild) => {
|
|
433
|
+
setIsShowingInnerSheet(hasChild);
|
|
434
|
+
}, []);
|
|
435
|
+
(0, import_core.useIsomorphicLayoutEffect)(() => {
|
|
436
|
+
if (!parentSheetContext || !open)
|
|
437
|
+
return;
|
|
438
|
+
parentSheetContext(true);
|
|
439
|
+
return () => {
|
|
440
|
+
parentSheetContext(false);
|
|
441
|
+
};
|
|
442
|
+
}, [parentSheetContext, open]);
|
|
428
443
|
const contents = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_SheetContext.SheetProvider, {
|
|
429
444
|
modal,
|
|
430
445
|
contentRef,
|
|
@@ -439,7 +454,7 @@ const Sheet = (0, import_core.withStaticProperties)(
|
|
|
439
454
|
setOpen,
|
|
440
455
|
scrollBridge,
|
|
441
456
|
children: [
|
|
442
|
-
isResizing ? null : overlayComponent,
|
|
457
|
+
isResizing || shouldHideParentSheet ? null : overlayComponent,
|
|
443
458
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AnimatedView, {
|
|
444
459
|
ref,
|
|
445
460
|
...panResponder == null ? void 0 : panResponder.panHandlers,
|
|
@@ -451,13 +466,14 @@ const Sheet = (0, import_core.withStaticProperties)(
|
|
|
451
466
|
return next;
|
|
452
467
|
});
|
|
453
468
|
},
|
|
454
|
-
pointerEvents: open ? "auto" : "none",
|
|
469
|
+
pointerEvents: open && !shouldHideParentSheet ? "auto" : "none",
|
|
455
470
|
style: [
|
|
456
471
|
{
|
|
457
472
|
position: "absolute",
|
|
458
473
|
zIndex,
|
|
459
474
|
width: "100%",
|
|
460
|
-
height: "100%"
|
|
475
|
+
height: "100%",
|
|
476
|
+
opacity: shouldHideParentSheet ? 0 : 1
|
|
461
477
|
},
|
|
462
478
|
animatedStyle
|
|
463
479
|
],
|
|
@@ -476,19 +492,27 @@ const Sheet = (0, import_core.withStaticProperties)(
|
|
|
476
492
|
]
|
|
477
493
|
});
|
|
478
494
|
if (modal) {
|
|
479
|
-
|
|
495
|
+
const modalContents = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_portal.Portal, {
|
|
480
496
|
zIndex,
|
|
481
497
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Theme, {
|
|
482
498
|
name: themeName,
|
|
483
499
|
children: contents
|
|
484
500
|
})
|
|
485
501
|
});
|
|
502
|
+
if (import_core.isWeb) {
|
|
503
|
+
return modalContents;
|
|
504
|
+
}
|
|
505
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SheetInsideSheetContext.Provider, {
|
|
506
|
+
value: onInnerSheet,
|
|
507
|
+
children: modalContents
|
|
508
|
+
});
|
|
486
509
|
}
|
|
487
510
|
return contents;
|
|
488
511
|
})
|
|
489
512
|
),
|
|
490
513
|
sheetComponents
|
|
491
514
|
);
|
|
515
|
+
const SheetInsideSheetContext = (0, import_react.createContext)(null);
|
|
492
516
|
const ControlledSheet = Sheet;
|
|
493
517
|
function getPercentSize(point, frameSize) {
|
|
494
518
|
if (!frameSize)
|
package/dist/cjs/Sheet.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/Sheet.tsx"],
|
|
4
|
-
"sourcesContent": ["import { useComposedRefs } from '@tamagui/compose-refs'\nimport {\n GetProps,\n Slot,\n TamaguiElement,\n Theme,\n getAnimationDriver,\n isClient,\n mergeEvent,\n styled,\n themeable,\n useConstant,\n useEvent,\n useIsomorphicLayoutEffect,\n useThemeName,\n withStaticProperties,\n} from '@tamagui/core'\nimport { Portal } from '@tamagui/portal'\nimport { RemoveScroll } from '@tamagui/remove-scroll'\nimport { XStack, XStackProps, YStack, YStackProps } from '@tamagui/stacks'\nimport { useControllableState } from '@tamagui/use-controllable-state'\nimport React, {\n FunctionComponent,\n RefAttributes,\n createContext,\n forwardRef,\n isValidElement,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport { GestureResponderEvent, PanResponder, PanResponderGestureState, View } from 'react-native'\n\nimport { SHEET_HANDLE_NAME, SHEET_NAME } from './SHEET_HANDLE_NAME'\nimport { SheetProvider, useSheetContext } from './SheetContext'\nimport { SheetScrollView } from './SheetScrollView'\nimport { ScrollBridge, SheetProps, SheetScopedProps } from './types'\n\nexport { createSheetScope } from './SheetContext'\n\n/* -------------------------------------------------------------------------------------------------\n * SheetHandle\n * -----------------------------------------------------------------------------------------------*/\n\nexport const SheetHandleFrame = styled(XStack, {\n name: SHEET_HANDLE_NAME,\n height: 10,\n borderRadius: 100,\n backgroundColor: '$background',\n zIndex: 10,\n marginHorizontal: '35%',\n marginBottom: '$2',\n opacity: 0.5,\n\n hoverStyle: {\n opacity: 0.7,\n },\n\n variants: {\n open: {\n true: {\n pointerEvents: 'auto',\n },\n false: {\n opacity: 0,\n pointerEvents: 'none',\n },\n },\n } as const,\n})\n\nexport const SheetHandle = SheetHandleFrame.extractable(\n ({ __scopeSheet, ...props }: SheetScopedProps<XStackProps>) => {\n const context = useSheetContext(SHEET_HANDLE_NAME, __scopeSheet)\n return (\n <SheetHandleFrame\n onPress={() => {\n // don't toggle to the bottom snap position when dismissOnSnapToBottom set\n const max = context.snapPoints.length + (context.dismissOnSnapToBottom ? -1 : 0)\n const nextPos = (context.position + 1) % max\n context.setPosition(nextPos)\n }}\n open={context.open}\n {...props}\n />\n )\n }\n)\n\n/* -------------------------------------------------------------------------------------------------\n * SheetOverlay\n * -----------------------------------------------------------------------------------------------*/\n\nconst SHEET_OVERLAY_NAME = 'SheetOverlay'\n\nexport const SheetOverlayFrame = styled(YStack, {\n name: SHEET_OVERLAY_NAME,\n // TODO this should be $background without opacity and just customized by theme\n backgroundColor: '$color',\n fullscreen: true,\n opacity: 0.2,\n zIndex: 0,\n\n variants: {\n closed: {\n true: {\n opacity: 0,\n pointerEvents: 'none',\n },\n false: {\n pointerEvents: 'auto',\n },\n },\n } as const,\n})\n\nexport type SheetOverlayProps = GetProps<typeof SheetOverlayFrame>\n\nexport const SheetOverlay = SheetOverlayFrame.extractable(\n ({ __scopeSheet, ...props }: SheetScopedProps<SheetOverlayProps>) => {\n const context = useSheetContext(SHEET_OVERLAY_NAME, __scopeSheet)\n return (\n <SheetOverlayFrame\n closed={!context.open || context.hidden}\n {...props}\n onPress={mergeEvent(\n props.onPress,\n context.dismissOnOverlayPress\n ? () => {\n context.setOpen(false)\n }\n : undefined\n )}\n />\n )\n }\n)\n\n/* -------------------------------------------------------------------------------------------------\n * Sheet\n * -----------------------------------------------------------------------------------------------*/\n\nconst selectionStyleSheet = isClient ? document.createElement('style') : null\nif (selectionStyleSheet) {\n document.head.appendChild(selectionStyleSheet)\n}\n\nexport const SheetFrameFrame = styled(YStack, {\n name: SHEET_NAME,\n flex: 1,\n backgroundColor: '$background',\n borderTopLeftRadius: '$4',\n borderTopRightRadius: '$4',\n width: '100%',\n maxHeight: '100%',\n overflow: 'hidden',\n pointerEvents: 'auto',\n})\n\nexport const SheetFrame = SheetFrameFrame.extractable(\n forwardRef(({ __scopeSheet, ...props }: SheetScopedProps<YStackProps>, forwardedRef) => {\n const context = useSheetContext(SHEET_NAME, __scopeSheet)\n const composedContentRef = useComposedRefs(forwardedRef, context.contentRef)\n return <SheetFrameFrame ref={composedContentRef} {...props} />\n })\n)\n\n// set all the way off screen\nconst HIDDEN_SIZE = 10_000\n\nconst sheetComponents = {\n Handle: SheetHandle,\n Frame: SheetFrame,\n Overlay: SheetOverlay,\n ScrollView: SheetScrollView,\n}\n\nexport const Sheet = withStaticProperties(\n themeable(\n forwardRef<View, SheetProps>(function Sheet(props, ref) {\n const {\n __scopeSheet,\n snapPoints: snapPointsProp = [80],\n open: openProp,\n defaultOpen,\n children: childrenProp,\n position: positionProp,\n onPositionChange,\n onOpenChange,\n defaultPosition,\n dismissOnOverlayPress = true,\n animationConfig,\n dismissOnSnapToBottom = false,\n disableDrag: disableDragProp,\n modal = false,\n handleDisableScroll = true,\n zIndex = 40,\n } = props\n\n if (process.env.NODE_ENV === 'development') {\n if (snapPointsProp.some((p) => p < 0 || p > 100)) {\n // eslint-disable-next-line no-console\n console.warn(\n `\u26A0\uFE0F Invalid snapPoint given, snapPoints must be between 0 and 100, equal to percent height of frame`\n )\n }\n }\n\n const driver = getAnimationDriver()\n if (!driver) {\n throw new Error(`Must set animations in tamagui.config.ts`)\n }\n\n // allows for sheets to be controlled by other components\n const controller = useContext(SheetControllerContext)\n const isHidden = controller?.hidden || false\n const disableDrag = disableDragProp ?? controller?.disableDrag\n const themeName = useThemeName()\n const contentRef = React.useRef<TamaguiElement>(null)\n const scrollBridge = useConstant<ScrollBridge>(() => ({\n enabled: false,\n y: 0,\n paneY: 0,\n paneMinY: 0,\n scrollStartY: -1,\n drag: () => {},\n release: () => {},\n scrollLock: false,\n }))\n\n const onOpenChangeInternal = (val: boolean) => {\n controller?.onOpenChange?.(val)\n onOpenChange?.(val)\n }\n\n const [open, setOpen] = useControllableState({\n prop: controller?.open ?? openProp,\n defaultProp: defaultOpen || true,\n onChange: onOpenChangeInternal,\n strategy: 'most-recent-wins',\n })\n\n const [frameSize, setFrameSize] = useState<number>(0)\n\n const snapPoints = useMemo(\n () => (dismissOnSnapToBottom ? [...snapPointsProp, 0] : snapPointsProp),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(snapPointsProp), dismissOnSnapToBottom]\n )\n\n // lets set -1 to be always the \"open = false\" position\n const [position_, setPosition_] = useControllableState({\n prop: positionProp,\n defaultProp: defaultPosition || (open ? 0 : -1),\n onChange: onPositionChange,\n strategy: 'most-recent-wins',\n })\n const position = open === false ? -1 : position_\n\n // reset position to fully open on re-open after dismissOnSnapToBottom\n if (open && dismissOnSnapToBottom && position === snapPoints.length - 1) {\n setPosition_(0)\n }\n\n const setPosition = useCallback(\n (next: number) => {\n // close on dismissOnSnapToBottom (and set position so it animates)\n if (dismissOnSnapToBottom && next === snapPoints.length - 1) {\n setOpen(false)\n } else {\n setPosition_(next)\n }\n },\n [dismissOnSnapToBottom, snapPoints.length, setPosition_, setOpen]\n )\n\n const animatedNumber = driver.useAnimatedNumber(HIDDEN_SIZE)\n\n // native only fix\n const at = useRef(0)\n driver.useAnimatedNumberReaction(animatedNumber, (value) => {\n at.current = value\n scrollBridge.paneY = value\n })\n\n const [isResizing, setIsResizing] = useState(true)\n useIsomorphicLayoutEffect(() => {\n if (!isResizing) {\n setIsResizing(true)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [modal])\n\n function stopSpring() {\n animatedNumber.stop()\n if (scrollBridge.onFinishAnimate) {\n scrollBridge.onFinishAnimate()\n scrollBridge.onFinishAnimate = undefined\n }\n }\n\n // open must set position\n const shouldSetPositionOpen = open && position < 0\n useEffect(() => {\n if (shouldSetPositionOpen) {\n setPosition(0)\n }\n }, [setPosition, shouldSetPositionOpen])\n\n const positions = useMemo(\n () => snapPoints.map((point) => getPercentSize(point, frameSize)),\n [frameSize, snapPoints]\n )\n\n const animateTo = useEvent((position: number) => {\n const current = animatedNumber.getValue()\n if (isHidden && open) return\n if (!current) return\n if (frameSize === 0) return\n const hiddenValue = frameSize === 0 ? HIDDEN_SIZE : frameSize\n const toValue = isHidden || position === -1 ? hiddenValue : positions[position]\n if (at.current === toValue) return\n stopSpring()\n if (isHidden || isResizing) {\n if (isResizing) {\n setIsResizing(false)\n }\n animatedNumber.setValue(toValue, {\n type: 'timing',\n duration: 0,\n })\n at.current = toValue\n return\n }\n // dont bounce on initial measure to bottom\n const overshootClamping = at.current === HIDDEN_SIZE\n animatedNumber.setValue(toValue, {\n ...animationConfig,\n type: 'spring',\n overshootClamping,\n })\n })\n\n useIsomorphicLayoutEffect(() => {\n animateTo(position)\n }, [isHidden, frameSize, position, animateTo])\n\n const panResponder = useMemo(\n () => {\n if (disableDrag) return\n if (!frameSize) return\n\n const minY = positions[0]\n scrollBridge.paneMinY = minY\n let startY = at.current\n\n function makeUnselectable(val: boolean) {\n if (!selectionStyleSheet) return\n if (!val) {\n selectionStyleSheet.innerText = ``\n } else {\n selectionStyleSheet.innerText = `:root * { user-select: none !important; -webkit-user-select: none !important; }`\n }\n }\n\n const release = ({ vy, dragAt }: { dragAt: number; vy: number }) => {\n isExternalDrag = false\n previouslyScrolling = false\n makeUnselectable(false)\n const at = dragAt + startY\n // seems liky vy goes up to about 4 at the very most (+ is down, - is up)\n // lets base our multiplier on the total layout height\n const end = at + frameSize * vy * 0.2\n let closestPoint = 0\n let dist = Infinity\n for (let i = 0; i < positions.length; i++) {\n const position = positions[i]\n const curDist = end > position ? end - position : position - end\n if (curDist < dist) {\n dist = curDist\n closestPoint = i\n }\n }\n // have to call both because state may not change but need to snap back\n setPosition(closestPoint)\n animateTo(closestPoint)\n }\n\n const finish = (_e: GestureResponderEvent, state: PanResponderGestureState) => {\n release({\n vy: state.vy,\n dragAt: state.dy,\n })\n }\n\n let previouslyScrolling = false\n\n const onMoveShouldSet = (_e: GestureResponderEvent, { dy }: PanResponderGestureState) => {\n const isScrolled = scrollBridge.y !== 0\n if (isScrolled) {\n previouslyScrolling = true\n return false\n }\n if (previouslyScrolling) {\n previouslyScrolling = false\n return true\n }\n const isDraggingUp = dy < 0\n const isAtTop = scrollBridge.paneY <= scrollBridge.paneMinY\n // prevent drag once at top and pulling up\n if (isAtTop) {\n if (!isScrolled && isDraggingUp) {\n return false\n }\n }\n // we could do some detection of other touchables and cancel here..\n return Math.abs(dy) > 8\n }\n\n const grant = () => {\n makeUnselectable(true)\n stopSpring()\n startY = at.current\n }\n\n let isExternalDrag = false\n\n scrollBridge.drag = (dy) => {\n if (!isExternalDrag) {\n isExternalDrag = true\n grant()\n }\n const to = dy + startY\n animatedNumber.setValue(resisted(to, minY), { type: 'direct' })\n }\n\n scrollBridge.release = release\n\n return PanResponder.create({\n onMoveShouldSetPanResponder: onMoveShouldSet,\n onPanResponderGrant: grant,\n onPanResponderMove: (_e, { dy }) => {\n const to = dy + startY\n animatedNumber.setValue(resisted(to, minY), { type: 'direct' })\n },\n onPanResponderEnd: finish,\n onPanResponderTerminate: finish,\n onPanResponderRelease: finish,\n })\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [disableDrag, animateTo, frameSize, positions, setPosition]\n )\n\n let handleComponent: React.ReactElement | null = null\n let overlayComponent: React.ReactElement | null = null\n let frameComponent: React.ReactElement | null = null\n\n // TODO do more radix-like and don't require direct children descendents\n React.Children.forEach(childrenProp, (child) => {\n if (isValidElement(child)) {\n const name = child.type?.['staticConfig']?.componentName\n switch (name) {\n case 'SheetHandle':\n handleComponent = child\n break\n case 'Sheet':\n frameComponent = child\n break\n case 'SheetOverlay':\n overlayComponent = child\n break\n default:\n // eslint-disable-next-line no-console\n console.warn('Warning: passed invalid child to Sheet', child)\n }\n }\n })\n\n const preventShown = controller?.hidden && controller?.open\n\n const animatedStyle = driver.useAnimatedNumberStyle(animatedNumber, (val) => {\n return {\n transform: [{ translateY: frameSize === 0 ? HIDDEN_SIZE : val }],\n }\n })\n\n if (preventShown) {\n return null\n }\n\n // temp until reanimated useAnimatedNumber fix\n const AnimatedView = driver['NumberView'] ?? driver.View\n\n const contents = (\n <SheetProvider\n modal={modal}\n contentRef={contentRef}\n dismissOnOverlayPress={dismissOnOverlayPress}\n dismissOnSnapToBottom={dismissOnSnapToBottom}\n open={open}\n hidden={isHidden}\n scope={__scopeSheet}\n position={position}\n snapPoints={snapPoints}\n setPosition={setPosition}\n setOpen={setOpen}\n scrollBridge={scrollBridge}\n >\n {isResizing ? null : overlayComponent}\n\n <AnimatedView\n ref={ref}\n {...panResponder?.panHandlers}\n onLayout={(e) => {\n const next = e.nativeEvent.layout.height\n setFrameSize((prev) => {\n const isBigChange = Math.abs(prev - next) > 50\n setIsResizing(isBigChange)\n return next\n })\n }}\n pointerEvents={open ? 'auto' : 'none'}\n style={[\n {\n position: 'absolute',\n zIndex,\n width: '100%',\n height: '100%',\n },\n animatedStyle,\n ]}\n >\n {handleComponent}\n\n <RemoveScroll\n enabled={open && modal && handleDisableScroll}\n as={Slot}\n allowPinchZoom\n shards={[contentRef]}\n // causes lots of bugs on touch web on site\n removeScrollBar={false}\n >\n {isResizing ? null : frameComponent}\n </RemoveScroll>\n </AnimatedView>\n </SheetProvider>\n )\n\n if (modal) {\n return (\n <Portal zIndex={zIndex}>\n <Theme name={themeName}>{contents}</Theme>\n </Portal>\n )\n }\n\n return contents\n })\n ),\n sheetComponents\n)\n\nexport const ControlledSheet = Sheet as FunctionComponent<\n Omit<SheetProps, 'open' | 'onOpenChange'> & RefAttributes<View>\n> &\n typeof sheetComponents\n\n/* -------------------------------------------------------------------------------------------------*/\n\nfunction getPercentSize(point?: number, frameSize?: number) {\n if (!frameSize) return 0\n if (point === undefined) {\n // eslint-disable-next-line no-console\n console.warn(`No snapPoint`)\n return 0\n }\n const pct = point / 100\n const next = Math.round(frameSize - pct * frameSize)\n return next\n}\n\nfunction resisted(y: number, minY: number, maxOverflow = 25) {\n if (y < minY) {\n const past = minY - y\n const pctPast = Math.min(maxOverflow, past) / maxOverflow\n const diminishBy = 1.1 - Math.pow(0.1, pctPast)\n const extra = -diminishBy * maxOverflow\n return minY + extra\n }\n return y\n}\n\ntype SheetControllerContextValue = {\n disableDrag?: boolean\n open?: boolean\n // hide without \"closing\" to prevent re-animation when shown again\n hidden?: boolean\n onOpenChange?: React.Dispatch<React.SetStateAction<boolean>> | ((val: boolean) => void)\n}\n\nconst SheetControllerContext = createContext<SheetControllerContextValue | null>(null)\n\nexport const SheetController = ({\n children,\n onOpenChange: onOpenChangeProp,\n ...value\n}: Partial<SheetControllerContextValue> & { children?: React.ReactNode }) => {\n const onOpenChange = useEvent(onOpenChangeProp)\n\n const memoValue = useMemo(\n () => ({\n open: value.open,\n hidden: value.hidden,\n disableDrag: value.disableDrag,\n onOpenChange,\n }),\n [onOpenChange, value.open, value.hidden, value.disableDrag]\n )\n\n return (\n <SheetControllerContext.Provider value={memoValue}>{children}</SheetControllerContext.Provider>\n )\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import { useComposedRefs } from '@tamagui/compose-refs'\nimport {\n GetProps,\n Slot,\n TamaguiElement,\n Theme,\n getAnimationDriver,\n isClient,\n isWeb,\n mergeEvent,\n styled,\n themeable,\n useConstant,\n useEvent,\n useIsomorphicLayoutEffect,\n useThemeName,\n withStaticProperties,\n} from '@tamagui/core'\nimport { Portal } from '@tamagui/portal'\nimport { RemoveScroll } from '@tamagui/remove-scroll'\nimport { XStack, XStackProps, YStack, YStackProps } from '@tamagui/stacks'\nimport { useControllableState } from '@tamagui/use-controllable-state'\nimport React, {\n FunctionComponent,\n RefAttributes,\n createContext,\n forwardRef,\n isValidElement,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport { GestureResponderEvent, PanResponder, PanResponderGestureState, View } from 'react-native'\n\nimport { SHEET_HANDLE_NAME, SHEET_NAME } from './SHEET_HANDLE_NAME'\nimport { SheetProvider, useSheetContext } from './SheetContext'\nimport { SheetScrollView } from './SheetScrollView'\nimport { ScrollBridge, SheetProps, SheetScopedProps } from './types'\n\nexport { createSheetScope } from './SheetContext'\n\n/* -------------------------------------------------------------------------------------------------\n * SheetHandle\n * -----------------------------------------------------------------------------------------------*/\n\nexport const SheetHandleFrame = styled(XStack, {\n name: SHEET_HANDLE_NAME,\n height: 10,\n borderRadius: 100,\n backgroundColor: '$background',\n zIndex: 10,\n marginHorizontal: '35%',\n marginBottom: '$2',\n opacity: 0.5,\n\n hoverStyle: {\n opacity: 0.7,\n },\n\n variants: {\n open: {\n true: {\n pointerEvents: 'auto',\n },\n false: {\n opacity: 0,\n pointerEvents: 'none',\n },\n },\n } as const,\n})\n\nexport const SheetHandle = SheetHandleFrame.extractable(\n ({ __scopeSheet, ...props }: SheetScopedProps<XStackProps>) => {\n const context = useSheetContext(SHEET_HANDLE_NAME, __scopeSheet)\n return (\n <SheetHandleFrame\n onPress={() => {\n // don't toggle to the bottom snap position when dismissOnSnapToBottom set\n const max = context.snapPoints.length + (context.dismissOnSnapToBottom ? -1 : 0)\n const nextPos = (context.position + 1) % max\n context.setPosition(nextPos)\n }}\n open={context.open}\n {...props}\n />\n )\n }\n)\n\n/* -------------------------------------------------------------------------------------------------\n * SheetOverlay\n * -----------------------------------------------------------------------------------------------*/\n\nconst SHEET_OVERLAY_NAME = 'SheetOverlay'\n\nexport const SheetOverlayFrame = styled(YStack, {\n name: SHEET_OVERLAY_NAME,\n // TODO this should be $background without opacity and just customized by theme\n backgroundColor: '$color',\n fullscreen: true,\n opacity: 0.2,\n zIndex: 0,\n\n variants: {\n closed: {\n true: {\n opacity: 0,\n pointerEvents: 'none',\n },\n false: {\n pointerEvents: 'auto',\n },\n },\n } as const,\n})\n\nexport type SheetOverlayProps = GetProps<typeof SheetOverlayFrame>\n\nexport const SheetOverlay = SheetOverlayFrame.extractable(\n ({ __scopeSheet, ...props }: SheetScopedProps<SheetOverlayProps>) => {\n const context = useSheetContext(SHEET_OVERLAY_NAME, __scopeSheet)\n return (\n <SheetOverlayFrame\n closed={!context.open || context.hidden}\n {...props}\n onPress={mergeEvent(\n props.onPress,\n context.dismissOnOverlayPress\n ? () => {\n context.setOpen(false)\n }\n : undefined\n )}\n />\n )\n }\n)\n\n/* -------------------------------------------------------------------------------------------------\n * Sheet\n * -----------------------------------------------------------------------------------------------*/\n\nconst selectionStyleSheet = isClient ? document.createElement('style') : null\nif (selectionStyleSheet) {\n document.head.appendChild(selectionStyleSheet)\n}\n\nexport const SheetFrameFrame = styled(YStack, {\n name: SHEET_NAME,\n flex: 1,\n backgroundColor: '$background',\n borderTopLeftRadius: '$4',\n borderTopRightRadius: '$4',\n width: '100%',\n maxHeight: '100%',\n overflow: 'hidden',\n pointerEvents: 'auto',\n})\n\nexport const SheetFrame = SheetFrameFrame.extractable(\n forwardRef(({ __scopeSheet, ...props }: SheetScopedProps<YStackProps>, forwardedRef) => {\n const context = useSheetContext(SHEET_NAME, __scopeSheet)\n const composedContentRef = useComposedRefs(forwardedRef, context.contentRef)\n return <SheetFrameFrame ref={composedContentRef} {...props} />\n })\n)\n\n// set all the way off screen\nconst HIDDEN_SIZE = 10_000\n\nconst sheetComponents = {\n Handle: SheetHandle,\n Frame: SheetFrame,\n Overlay: SheetOverlay,\n ScrollView: SheetScrollView,\n}\n\nexport const Sheet = withStaticProperties(\n themeable(\n forwardRef<View, SheetProps>(function Sheet(props, ref) {\n const {\n __scopeSheet,\n snapPoints: snapPointsProp = [80],\n open: openProp,\n defaultOpen,\n children: childrenProp,\n position: positionProp,\n onPositionChange,\n onOpenChange,\n defaultPosition,\n dismissOnOverlayPress = true,\n animationConfig,\n dismissOnSnapToBottom = false,\n disableDrag: disableDragProp,\n modal = false,\n handleDisableScroll = true,\n zIndex = 40,\n } = props\n\n if (process.env.NODE_ENV === 'development') {\n if (snapPointsProp.some((p) => p < 0 || p > 100)) {\n // eslint-disable-next-line no-console\n console.warn(\n `\u26A0\uFE0F Invalid snapPoint given, snapPoints must be between 0 and 100, equal to percent height of frame`\n )\n }\n }\n\n const driver = getAnimationDriver()\n if (!driver) {\n throw new Error(`Must set animations in tamagui.config.ts`)\n }\n\n // allows for sheets to be controlled by other components\n const controller = useContext(SheetControllerContext)\n const isHidden = controller?.hidden || false\n const disableDrag = disableDragProp ?? controller?.disableDrag\n const themeName = useThemeName()\n const contentRef = React.useRef<TamaguiElement>(null)\n const scrollBridge = useConstant<ScrollBridge>(() => ({\n enabled: false,\n y: 0,\n paneY: 0,\n paneMinY: 0,\n scrollStartY: -1,\n drag: () => {},\n release: () => {},\n scrollLock: false,\n }))\n\n const onOpenChangeInternal = (val: boolean) => {\n controller?.onOpenChange?.(val)\n onOpenChange?.(val)\n }\n\n const [open, setOpen] = useControllableState({\n prop: controller?.open ?? openProp,\n defaultProp: defaultOpen || true,\n onChange: onOpenChangeInternal,\n strategy: 'most-recent-wins',\n })\n\n const [frameSize, setFrameSize] = useState<number>(0)\n\n const snapPoints = useMemo(\n () => (dismissOnSnapToBottom ? [...snapPointsProp, 0] : snapPointsProp),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(snapPointsProp), dismissOnSnapToBottom]\n )\n\n // lets set -1 to be always the \"open = false\" position\n const [position_, setPosition_] = useControllableState({\n prop: positionProp,\n defaultProp: defaultPosition || (open ? 0 : -1),\n onChange: onPositionChange,\n strategy: 'most-recent-wins',\n })\n const position = open === false ? -1 : position_\n\n // reset position to fully open on re-open after dismissOnSnapToBottom\n if (open && dismissOnSnapToBottom && position === snapPoints.length - 1) {\n setPosition_(0)\n }\n\n const setPosition = useCallback(\n (next: number) => {\n // close on dismissOnSnapToBottom (and set position so it animates)\n if (dismissOnSnapToBottom && next === snapPoints.length - 1) {\n setOpen(false)\n } else {\n setPosition_(next)\n }\n },\n [dismissOnSnapToBottom, snapPoints.length, setPosition_, setOpen]\n )\n\n const animatedNumber = driver.useAnimatedNumber(HIDDEN_SIZE)\n\n // native only fix\n const at = useRef(0)\n driver.useAnimatedNumberReaction(animatedNumber, (value) => {\n at.current = value\n scrollBridge.paneY = value\n })\n\n const [isResizing, setIsResizing] = useState(true)\n useIsomorphicLayoutEffect(() => {\n if (!isResizing) {\n setIsResizing(true)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [modal])\n\n function stopSpring() {\n animatedNumber.stop()\n if (scrollBridge.onFinishAnimate) {\n scrollBridge.onFinishAnimate()\n scrollBridge.onFinishAnimate = undefined\n }\n }\n\n // open must set position\n const shouldSetPositionOpen = open && position < 0\n useEffect(() => {\n if (shouldSetPositionOpen) {\n setPosition(0)\n }\n }, [setPosition, shouldSetPositionOpen])\n\n const positions = useMemo(\n () => snapPoints.map((point) => getPercentSize(point, frameSize)),\n [frameSize, snapPoints]\n )\n\n const animateTo = useEvent((position: number) => {\n const current = animatedNumber.getValue()\n if (isHidden && open) return\n if (!current) return\n if (frameSize === 0) return\n const hiddenValue = frameSize === 0 ? HIDDEN_SIZE : frameSize\n const toValue = isHidden || position === -1 ? hiddenValue : positions[position]\n if (at.current === toValue) return\n stopSpring()\n if (isHidden || isResizing) {\n if (isResizing) {\n setIsResizing(false)\n }\n animatedNumber.setValue(toValue, {\n type: 'timing',\n duration: 0,\n })\n at.current = toValue\n return\n }\n // dont bounce on initial measure to bottom\n const overshootClamping = at.current === HIDDEN_SIZE\n animatedNumber.setValue(toValue, {\n ...animationConfig,\n type: 'spring',\n overshootClamping,\n })\n })\n\n useIsomorphicLayoutEffect(() => {\n animateTo(position)\n }, [isHidden, frameSize, position, animateTo])\n\n const panResponder = useMemo(\n () => {\n if (disableDrag) return\n if (!frameSize) return\n\n const minY = positions[0]\n scrollBridge.paneMinY = minY\n let startY = at.current\n\n function makeUnselectable(val: boolean) {\n if (!selectionStyleSheet) return\n if (!val) {\n selectionStyleSheet.innerText = ``\n } else {\n selectionStyleSheet.innerText = `:root * { user-select: none !important; -webkit-user-select: none !important; }`\n }\n }\n\n const release = ({ vy, dragAt }: { dragAt: number; vy: number }) => {\n isExternalDrag = false\n previouslyScrolling = false\n makeUnselectable(false)\n const at = dragAt + startY\n // seems liky vy goes up to about 4 at the very most (+ is down, - is up)\n // lets base our multiplier on the total layout height\n const end = at + frameSize * vy * 0.2\n let closestPoint = 0\n let dist = Infinity\n for (let i = 0; i < positions.length; i++) {\n const position = positions[i]\n const curDist = end > position ? end - position : position - end\n if (curDist < dist) {\n dist = curDist\n closestPoint = i\n }\n }\n // have to call both because state may not change but need to snap back\n setPosition(closestPoint)\n animateTo(closestPoint)\n }\n\n const finish = (_e: GestureResponderEvent, state: PanResponderGestureState) => {\n release({\n vy: state.vy,\n dragAt: state.dy,\n })\n }\n\n let previouslyScrolling = false\n\n const onMoveShouldSet = (_e: GestureResponderEvent, { dy }: PanResponderGestureState) => {\n const isScrolled = scrollBridge.y !== 0\n if (isScrolled) {\n previouslyScrolling = true\n return false\n }\n if (previouslyScrolling) {\n previouslyScrolling = false\n return true\n }\n const isDraggingUp = dy < 0\n const isAtTop = scrollBridge.paneY <= scrollBridge.paneMinY\n // prevent drag once at top and pulling up\n if (isAtTop) {\n if (!isScrolled && isDraggingUp) {\n return false\n }\n }\n // we could do some detection of other touchables and cancel here..\n return Math.abs(dy) > 8\n }\n\n const grant = () => {\n makeUnselectable(true)\n stopSpring()\n startY = at.current\n }\n\n let isExternalDrag = false\n\n scrollBridge.drag = (dy) => {\n if (!isExternalDrag) {\n isExternalDrag = true\n grant()\n }\n const to = dy + startY\n animatedNumber.setValue(resisted(to, minY), { type: 'direct' })\n }\n\n scrollBridge.release = release\n\n return PanResponder.create({\n onMoveShouldSetPanResponder: onMoveShouldSet,\n onPanResponderGrant: grant,\n onPanResponderMove: (_e, { dy }) => {\n const toFull = dy + startY\n const to = resisted(toFull, minY)\n animatedNumber.setValue(to, { type: 'direct' })\n },\n onPanResponderEnd: finish,\n onPanResponderTerminate: finish,\n onPanResponderRelease: finish,\n })\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [disableDrag, animateTo, frameSize, positions, setPosition]\n )\n\n let handleComponent: React.ReactElement | null = null\n let overlayComponent: React.ReactElement | null = null\n let frameComponent: React.ReactElement | null = null\n\n // TODO do more radix-like and don't require direct children descendents\n React.Children.forEach(childrenProp, (child) => {\n if (isValidElement(child)) {\n const name = child.type?.['staticConfig']?.componentName\n switch (name) {\n case 'SheetHandle':\n handleComponent = child\n break\n case 'Sheet':\n frameComponent = child\n break\n case 'SheetOverlay':\n overlayComponent = child\n break\n default:\n // eslint-disable-next-line no-console\n console.warn('Warning: passed invalid child to Sheet', child)\n }\n }\n })\n\n const preventShown = controller?.hidden && controller?.open\n\n const animatedStyle = driver.useAnimatedNumberStyle(animatedNumber, (val) => {\n return {\n transform: [{ translateY: frameSize === 0 ? HIDDEN_SIZE : val }],\n }\n })\n\n if (preventShown) {\n return null\n }\n\n // temp until reanimated useAnimatedNumber fix\n const AnimatedView = driver['NumberView'] ?? driver.View\n\n /**\n * This is a hacky workaround for native:\n */\n const [isShowingInnerSheet, setIsShowingInnerSheet] = useState(false)\n const shouldHideParentSheet = !isWeb && modal && isShowingInnerSheet\n const parentSheetContext = useContext(SheetInsideSheetContext)\n const onInnerSheet = useCallback((hasChild: boolean) => {\n setIsShowingInnerSheet(hasChild)\n }, [])\n useIsomorphicLayoutEffect(() => {\n if (!parentSheetContext || !open) return\n parentSheetContext(true)\n return () => {\n parentSheetContext(false)\n }\n }, [parentSheetContext, open])\n\n const contents = (\n <SheetProvider\n modal={modal}\n contentRef={contentRef}\n dismissOnOverlayPress={dismissOnOverlayPress}\n dismissOnSnapToBottom={dismissOnSnapToBottom}\n open={open}\n hidden={isHidden}\n scope={__scopeSheet}\n position={position}\n snapPoints={snapPoints}\n setPosition={setPosition}\n setOpen={setOpen}\n scrollBridge={scrollBridge}\n >\n {isResizing || shouldHideParentSheet ? null : overlayComponent}\n\n <AnimatedView\n ref={ref}\n {...panResponder?.panHandlers}\n onLayout={(e) => {\n const next = e.nativeEvent.layout.height\n setFrameSize((prev) => {\n const isBigChange = Math.abs(prev - next) > 50\n setIsResizing(isBigChange)\n return next\n })\n }}\n pointerEvents={open && !shouldHideParentSheet ? 'auto' : 'none'}\n style={[\n {\n position: 'absolute',\n zIndex,\n width: '100%',\n height: '100%',\n opacity: shouldHideParentSheet ? 0 : 1,\n },\n animatedStyle,\n ]}\n >\n {handleComponent}\n\n <RemoveScroll\n enabled={open && modal && handleDisableScroll}\n as={Slot}\n allowPinchZoom\n shards={[contentRef]}\n // causes lots of bugs on touch web on site\n removeScrollBar={false}\n >\n {isResizing ? null : frameComponent}\n </RemoveScroll>\n </AnimatedView>\n </SheetProvider>\n )\n\n if (modal) {\n const modalContents = (\n <Portal zIndex={zIndex}>\n <Theme name={themeName}>{contents}</Theme>\n </Portal>\n )\n\n if (isWeb) {\n return modalContents\n }\n\n // on native we don't support multiple modals yet... fix for now is to hide outer one\n return (\n <SheetInsideSheetContext.Provider value={onInnerSheet}>\n {modalContents}\n </SheetInsideSheetContext.Provider>\n )\n }\n\n return contents\n })\n ),\n sheetComponents\n)\n\nconst SheetInsideSheetContext = createContext<((hasChild: boolean) => void) | null>(null)\n\nexport const ControlledSheet = Sheet as FunctionComponent<\n Omit<SheetProps, 'open' | 'onOpenChange'> & RefAttributes<View>\n> &\n typeof sheetComponents\n\n/* -------------------------------------------------------------------------------------------------*/\n\nfunction getPercentSize(point?: number, frameSize?: number) {\n if (!frameSize) return 0\n if (point === undefined) {\n // eslint-disable-next-line no-console\n console.warn(`No snapPoint`)\n return 0\n }\n const pct = point / 100\n const next = Math.round(frameSize - pct * frameSize)\n return next\n}\n\nfunction resisted(y: number, minY: number, maxOverflow = 25) {\n if (y < minY) {\n const past = minY - y\n const pctPast = Math.min(maxOverflow, past) / maxOverflow\n const diminishBy = 1.1 - Math.pow(0.1, pctPast)\n const extra = -diminishBy * maxOverflow\n return minY + extra\n }\n return y\n}\n\ntype SheetControllerContextValue = {\n disableDrag?: boolean\n open?: boolean\n // hide without \"closing\" to prevent re-animation when shown again\n hidden?: boolean\n onOpenChange?: React.Dispatch<React.SetStateAction<boolean>> | ((val: boolean) => void)\n}\n\nconst SheetControllerContext = createContext<SheetControllerContextValue | null>(null)\n\nexport const SheetController = ({\n children,\n onOpenChange: onOpenChangeProp,\n ...value\n}: Partial<SheetControllerContextValue> & { children?: React.ReactNode }) => {\n const onOpenChange = useEvent(onOpenChangeProp)\n\n const memoValue = useMemo(\n () => ({\n open: value.open,\n hidden: value.hidden,\n disableDrag: value.disableDrag,\n onOpenChange,\n }),\n [onOpenChange, value.open, value.hidden, value.disableDrag]\n )\n\n return (\n <SheetControllerContext.Provider value={memoValue}>{children}</SheetControllerContext.Provider>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["import_SheetContext", "Sheet", "React", "position", "at"]
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/SheetScrollView.tsx"],
|
|
4
|
-
"sourcesContent": ["import { TamaguiElement } from '@tamagui/core'\nimport { ScrollView, ScrollViewProps } from '@tamagui/scroll-view'\nimport { forwardRef, useRef, useState } from 'react'\n\nimport { useSheetContext } from './SheetContext'\nimport { SheetScopedProps } from './types'\n\n/* -------------------------------------------------------------------------------------------------\n * SheetScrollView\n * -----------------------------------------------------------------------------------------------*/\n\nconst SHEET_SCROLL_VIEW_NAME = 'SheetScrollView'\n\nexport const SheetScrollView = forwardRef<TamaguiElement, ScrollViewProps>(\n ({ __scopeSheet, ...props }: SheetScopedProps<ScrollViewProps>, ref) => {\n const { scrollBridge } = useSheetContext(SHEET_SCROLL_VIEW_NAME, __scopeSheet)\n const [scrollEnabled, setScrollEnabled] = useState(true)\n const state = useRef({\n lastPageY: 0,\n dragAt: 0,\n dys: [] as number[], // store a few recent dys to get velocity on release\n isScrolling: false,\n })\n\n const release = () => {\n scrollBridge.scrollStartY = -1\n state.current.isScrolling = false\n setScrollEnabled(true)\n let vy = 0\n if (state.current.dys.length) {\n const recentDys = state.current.dys.slice(-10)\n const dist = recentDys.length ? recentDys.reduce((a, b) => a + b, 0) : 0\n const avgDy = dist / recentDys.length\n vy = avgDy * 0.04\n }\n state.current.dys = []\n scrollBridge.release({\n dragAt: state.current.dragAt,\n vy,\n })\n }\n\n return (\n <ScrollView\n ref={ref}\n flex={1}\n scrollEventThrottle={8}\n scrollEnabled={scrollEnabled}\n onScroll={(e) => {\n const { y } = e.nativeEvent.contentOffset\n scrollBridge.y = y\n if (y > 0) {\n scrollBridge.scrollStartY = -1\n }\n }}\n onStartShouldSetResponder={() => {\n scrollBridge.scrollStartY = -1\n return true\n }}\n onMoveShouldSetResponder={() => true}\n onResponderMove={(e) => {\n const { pageY } = e.nativeEvent\n\n if (state.current.isScrolling) {\n return\n }\n\n if (scrollBridge.scrollStartY === -1) {\n scrollBridge.scrollStartY = pageY\n state.current.lastPageY = pageY\n }\n\n const dragAt = pageY - scrollBridge.scrollStartY\n const dy = pageY - state.current.lastPageY\n state.current.lastPageY = pageY // after dy\n
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import { TamaguiElement } from '@tamagui/core'\nimport { ScrollView, ScrollViewProps } from '@tamagui/scroll-view'\nimport { forwardRef, useRef, useState } from 'react'\n\nimport { useSheetContext } from './SheetContext'\nimport { SheetScopedProps } from './types'\n\n// TODO ideally would replicate https://github.com/ammarahm-ed/react-native-actions-sheet/blob/master/src/index.tsx\n\n/* -------------------------------------------------------------------------------------------------\n * SheetScrollView\n * -----------------------------------------------------------------------------------------------*/\n\nconst SHEET_SCROLL_VIEW_NAME = 'SheetScrollView'\n\nexport const SheetScrollView = forwardRef<TamaguiElement, ScrollViewProps>(\n ({ __scopeSheet, ...props }: SheetScopedProps<ScrollViewProps>, ref) => {\n const { scrollBridge } = useSheetContext(SHEET_SCROLL_VIEW_NAME, __scopeSheet)\n const [scrollEnabled, setScrollEnabled] = useState(true)\n const state = useRef({\n lastPageY: 0,\n dragAt: 0,\n dys: [] as number[], // store a few recent dys to get velocity on release\n isScrolling: false,\n })\n\n const release = () => {\n scrollBridge.scrollStartY = -1\n state.current.isScrolling = false\n setScrollEnabled(true)\n let vy = 0\n if (state.current.dys.length) {\n const recentDys = state.current.dys.slice(-10)\n const dist = recentDys.length ? recentDys.reduce((a, b) => a + b, 0) : 0\n const avgDy = dist / recentDys.length\n vy = avgDy * 0.04\n }\n state.current.dys = []\n scrollBridge.release({\n dragAt: state.current.dragAt,\n vy,\n })\n }\n\n return (\n <ScrollView\n ref={ref}\n flex={1}\n scrollEventThrottle={8}\n scrollEnabled={scrollEnabled}\n onScroll={(e) => {\n const { y } = e.nativeEvent.contentOffset\n scrollBridge.y = y\n if (y > 0) {\n scrollBridge.scrollStartY = -1\n }\n }}\n onStartShouldSetResponder={() => {\n scrollBridge.scrollStartY = -1\n return true\n }}\n onMoveShouldSetResponder={() => true}\n onResponderMove={(e) => {\n const { pageY } = e.nativeEvent\n\n if (state.current.isScrolling) {\n return\n }\n\n if (scrollBridge.scrollStartY === -1) {\n scrollBridge.scrollStartY = pageY\n state.current.lastPageY = pageY\n }\n\n const dragAt = pageY - scrollBridge.scrollStartY\n const dy = pageY - state.current.lastPageY\n state.current.lastPageY = pageY // after dy\n const isDraggingUp = dy < 0\n const isPaneAtTop = scrollBridge.paneY <= scrollBridge.paneMinY\n\n if ((dy === 0 || isDraggingUp) && isPaneAtTop) {\n state.current.isScrolling = true\n setScrollEnabled(true)\n return\n }\n\n setScrollEnabled(false)\n scrollBridge.drag(dragAt)\n state.current.dragAt = dragAt\n state.current.dys.push(dy)\n // only do every so often, cut down to 10 again\n if (state.current.dys.length > 100) {\n state.current.dys = state.current.dys.slice(-10)\n }\n }}\n onResponderRelease={release}\n {...props}\n />\n )\n }\n)\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA6CM;AA5CN,yBAA4C;AAC5C,mBAA6C;AAE7C,0BAAgC;AAShC,MAAM,yBAAyB;AAExB,MAAM,sBAAkB;AAAA,EAC7B,CAAC,EAAE,iBAAiB,MAAM,GAAsC,QAAQ;AACtE,UAAM,EAAE,aAAa,QAAI,qCAAgB,wBAAwB,YAAY;AAC7E,UAAM,CAAC,eAAe,gBAAgB,QAAI,uBAAS,IAAI;AACvD,UAAM,YAAQ,qBAAO;AAAA,MACnB,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,KAAK,CAAC;AAAA,MACN,aAAa;AAAA,IACf,CAAC;AAED,UAAM,UAAU,MAAM;AACpB,mBAAa,eAAe;AAC5B,YAAM,QAAQ,cAAc;AAC5B,uBAAiB,IAAI;AACrB,UAAI,KAAK;AACT,UAAI,MAAM,QAAQ,IAAI,QAAQ;AAC5B,cAAM,YAAY,MAAM,QAAQ,IAAI,MAAM,GAAG;AAC7C,cAAM,OAAO,UAAU,SAAS,UAAU,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI;AACvE,cAAM,QAAQ,OAAO,UAAU;AAC/B,aAAK,QAAQ;AAAA,MACf;AACA,YAAM,QAAQ,MAAM,CAAC;AACrB,mBAAa,QAAQ;AAAA,QACnB,QAAQ,MAAM,QAAQ;AAAA,QACtB;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WACE,4CAAC;AAAA,MACC;AAAA,MACA,MAAM;AAAA,MACN,qBAAqB;AAAA,MACrB;AAAA,MACA,UAAU,CAAC,MAAM;AACf,cAAM,EAAE,EAAE,IAAI,EAAE,YAAY;AAC5B,qBAAa,IAAI;AACjB,YAAI,IAAI,GAAG;AACT,uBAAa,eAAe;AAAA,QAC9B;AAAA,MACF;AAAA,MACA,2BAA2B,MAAM;AAC/B,qBAAa,eAAe;AAC5B,eAAO;AAAA,MACT;AAAA,MACA,0BAA0B,MAAM;AAAA,MAChC,iBAAiB,CAAC,MAAM;AACtB,cAAM,EAAE,MAAM,IAAI,EAAE;AAEpB,YAAI,MAAM,QAAQ,aAAa;AAC7B;AAAA,QACF;AAEA,YAAI,aAAa,iBAAiB,IAAI;AACpC,uBAAa,eAAe;AAC5B,gBAAM,QAAQ,YAAY;AAAA,QAC5B;AAEA,cAAM,SAAS,QAAQ,aAAa;AACpC,cAAM,KAAK,QAAQ,MAAM,QAAQ;AACjC,cAAM,QAAQ,YAAY;AAC1B,cAAM,eAAe,KAAK;AAC1B,cAAM,cAAc,aAAa,SAAS,aAAa;AAEvD,aAAK,OAAO,KAAK,iBAAiB,aAAa;AAC7C,gBAAM,QAAQ,cAAc;AAC5B,2BAAiB,IAAI;AACrB;AAAA,QACF;AAEA,yBAAiB,KAAK;AACtB,qBAAa,KAAK,MAAM;AACxB,cAAM,QAAQ,SAAS;AACvB,cAAM,QAAQ,IAAI,KAAK,EAAE;AAEzB,YAAI,MAAM,QAAQ,IAAI,SAAS,KAAK;AAClC,gBAAM,QAAQ,MAAM,MAAM,QAAQ,IAAI,MAAM,GAAG;AAAA,QACjD;AAAA,MACF;AAAA,MACA,oBAAoB;AAAA,MACnB,GAAG;AAAA,KACN;AAAA,EAEJ;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/esm/Sheet.js
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
Theme,
|
|
6
6
|
getAnimationDriver,
|
|
7
7
|
isClient,
|
|
8
|
+
isWeb,
|
|
8
9
|
mergeEvent,
|
|
9
10
|
styled,
|
|
10
11
|
themeable,
|
|
@@ -368,8 +369,9 @@ const Sheet = withStaticProperties(
|
|
|
368
369
|
onMoveShouldSetPanResponder: onMoveShouldSet,
|
|
369
370
|
onPanResponderGrant: grant,
|
|
370
371
|
onPanResponderMove: (_e, { dy }) => {
|
|
371
|
-
const
|
|
372
|
-
|
|
372
|
+
const toFull = dy + startY;
|
|
373
|
+
const to = resisted(toFull, minY);
|
|
374
|
+
animatedNumber.setValue(to, { type: "direct" });
|
|
373
375
|
},
|
|
374
376
|
onPanResponderEnd: finish,
|
|
375
377
|
onPanResponderTerminate: finish,
|
|
@@ -410,6 +412,20 @@ const Sheet = withStaticProperties(
|
|
|
410
412
|
return null;
|
|
411
413
|
}
|
|
412
414
|
const AnimatedView = driver["NumberView"] ?? driver.View;
|
|
415
|
+
const [isShowingInnerSheet, setIsShowingInnerSheet] = useState(false);
|
|
416
|
+
const shouldHideParentSheet = !isWeb && modal && isShowingInnerSheet;
|
|
417
|
+
const parentSheetContext = useContext(SheetInsideSheetContext);
|
|
418
|
+
const onInnerSheet = useCallback((hasChild) => {
|
|
419
|
+
setIsShowingInnerSheet(hasChild);
|
|
420
|
+
}, []);
|
|
421
|
+
useIsomorphicLayoutEffect(() => {
|
|
422
|
+
if (!parentSheetContext || !open)
|
|
423
|
+
return;
|
|
424
|
+
parentSheetContext(true);
|
|
425
|
+
return () => {
|
|
426
|
+
parentSheetContext(false);
|
|
427
|
+
};
|
|
428
|
+
}, [parentSheetContext, open]);
|
|
413
429
|
const contents = /* @__PURE__ */ jsxs(SheetProvider, {
|
|
414
430
|
modal,
|
|
415
431
|
contentRef,
|
|
@@ -424,7 +440,7 @@ const Sheet = withStaticProperties(
|
|
|
424
440
|
setOpen,
|
|
425
441
|
scrollBridge,
|
|
426
442
|
children: [
|
|
427
|
-
isResizing ? null : overlayComponent,
|
|
443
|
+
isResizing || shouldHideParentSheet ? null : overlayComponent,
|
|
428
444
|
/* @__PURE__ */ jsxs(AnimatedView, {
|
|
429
445
|
ref,
|
|
430
446
|
...panResponder == null ? void 0 : panResponder.panHandlers,
|
|
@@ -436,13 +452,14 @@ const Sheet = withStaticProperties(
|
|
|
436
452
|
return next;
|
|
437
453
|
});
|
|
438
454
|
},
|
|
439
|
-
pointerEvents: open ? "auto" : "none",
|
|
455
|
+
pointerEvents: open && !shouldHideParentSheet ? "auto" : "none",
|
|
440
456
|
style: [
|
|
441
457
|
{
|
|
442
458
|
position: "absolute",
|
|
443
459
|
zIndex,
|
|
444
460
|
width: "100%",
|
|
445
|
-
height: "100%"
|
|
461
|
+
height: "100%",
|
|
462
|
+
opacity: shouldHideParentSheet ? 0 : 1
|
|
446
463
|
},
|
|
447
464
|
animatedStyle
|
|
448
465
|
],
|
|
@@ -461,19 +478,27 @@ const Sheet = withStaticProperties(
|
|
|
461
478
|
]
|
|
462
479
|
});
|
|
463
480
|
if (modal) {
|
|
464
|
-
|
|
481
|
+
const modalContents = /* @__PURE__ */ jsx(Portal, {
|
|
465
482
|
zIndex,
|
|
466
483
|
children: /* @__PURE__ */ jsx(Theme, {
|
|
467
484
|
name: themeName,
|
|
468
485
|
children: contents
|
|
469
486
|
})
|
|
470
487
|
});
|
|
488
|
+
if (isWeb) {
|
|
489
|
+
return modalContents;
|
|
490
|
+
}
|
|
491
|
+
return /* @__PURE__ */ jsx(SheetInsideSheetContext.Provider, {
|
|
492
|
+
value: onInnerSheet,
|
|
493
|
+
children: modalContents
|
|
494
|
+
});
|
|
471
495
|
}
|
|
472
496
|
return contents;
|
|
473
497
|
})
|
|
474
498
|
),
|
|
475
499
|
sheetComponents
|
|
476
500
|
);
|
|
501
|
+
const SheetInsideSheetContext = createContext(null);
|
|
477
502
|
const ControlledSheet = Sheet;
|
|
478
503
|
function getPercentSize(point, frameSize) {
|
|
479
504
|
if (!frameSize)
|
package/dist/esm/Sheet.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/Sheet.tsx"],
|
|
4
|
-
"sourcesContent": ["import { useComposedRefs } from '@tamagui/compose-refs'\nimport {\n GetProps,\n Slot,\n TamaguiElement,\n Theme,\n getAnimationDriver,\n isClient,\n mergeEvent,\n styled,\n themeable,\n useConstant,\n useEvent,\n useIsomorphicLayoutEffect,\n useThemeName,\n withStaticProperties,\n} from '@tamagui/core'\nimport { Portal } from '@tamagui/portal'\nimport { RemoveScroll } from '@tamagui/remove-scroll'\nimport { XStack, XStackProps, YStack, YStackProps } from '@tamagui/stacks'\nimport { useControllableState } from '@tamagui/use-controllable-state'\nimport React, {\n FunctionComponent,\n RefAttributes,\n createContext,\n forwardRef,\n isValidElement,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport { GestureResponderEvent, PanResponder, PanResponderGestureState, View } from 'react-native'\n\nimport { SHEET_HANDLE_NAME, SHEET_NAME } from './SHEET_HANDLE_NAME'\nimport { SheetProvider, useSheetContext } from './SheetContext'\nimport { SheetScrollView } from './SheetScrollView'\nimport { ScrollBridge, SheetProps, SheetScopedProps } from './types'\n\nexport { createSheetScope } from './SheetContext'\n\n/* -------------------------------------------------------------------------------------------------\n * SheetHandle\n * -----------------------------------------------------------------------------------------------*/\n\nexport const SheetHandleFrame = styled(XStack, {\n name: SHEET_HANDLE_NAME,\n height: 10,\n borderRadius: 100,\n backgroundColor: '$background',\n zIndex: 10,\n marginHorizontal: '35%',\n marginBottom: '$2',\n opacity: 0.5,\n\n hoverStyle: {\n opacity: 0.7,\n },\n\n variants: {\n open: {\n true: {\n pointerEvents: 'auto',\n },\n false: {\n opacity: 0,\n pointerEvents: 'none',\n },\n },\n } as const,\n})\n\nexport const SheetHandle = SheetHandleFrame.extractable(\n ({ __scopeSheet, ...props }: SheetScopedProps<XStackProps>) => {\n const context = useSheetContext(SHEET_HANDLE_NAME, __scopeSheet)\n return (\n <SheetHandleFrame\n onPress={() => {\n // don't toggle to the bottom snap position when dismissOnSnapToBottom set\n const max = context.snapPoints.length + (context.dismissOnSnapToBottom ? -1 : 0)\n const nextPos = (context.position + 1) % max\n context.setPosition(nextPos)\n }}\n open={context.open}\n {...props}\n />\n )\n }\n)\n\n/* -------------------------------------------------------------------------------------------------\n * SheetOverlay\n * -----------------------------------------------------------------------------------------------*/\n\nconst SHEET_OVERLAY_NAME = 'SheetOverlay'\n\nexport const SheetOverlayFrame = styled(YStack, {\n name: SHEET_OVERLAY_NAME,\n // TODO this should be $background without opacity and just customized by theme\n backgroundColor: '$color',\n fullscreen: true,\n opacity: 0.2,\n zIndex: 0,\n\n variants: {\n closed: {\n true: {\n opacity: 0,\n pointerEvents: 'none',\n },\n false: {\n pointerEvents: 'auto',\n },\n },\n } as const,\n})\n\nexport type SheetOverlayProps = GetProps<typeof SheetOverlayFrame>\n\nexport const SheetOverlay = SheetOverlayFrame.extractable(\n ({ __scopeSheet, ...props }: SheetScopedProps<SheetOverlayProps>) => {\n const context = useSheetContext(SHEET_OVERLAY_NAME, __scopeSheet)\n return (\n <SheetOverlayFrame\n closed={!context.open || context.hidden}\n {...props}\n onPress={mergeEvent(\n props.onPress,\n context.dismissOnOverlayPress\n ? () => {\n context.setOpen(false)\n }\n : undefined\n )}\n />\n )\n }\n)\n\n/* -------------------------------------------------------------------------------------------------\n * Sheet\n * -----------------------------------------------------------------------------------------------*/\n\nconst selectionStyleSheet = isClient ? document.createElement('style') : null\nif (selectionStyleSheet) {\n document.head.appendChild(selectionStyleSheet)\n}\n\nexport const SheetFrameFrame = styled(YStack, {\n name: SHEET_NAME,\n flex: 1,\n backgroundColor: '$background',\n borderTopLeftRadius: '$4',\n borderTopRightRadius: '$4',\n width: '100%',\n maxHeight: '100%',\n overflow: 'hidden',\n pointerEvents: 'auto',\n})\n\nexport const SheetFrame = SheetFrameFrame.extractable(\n forwardRef(({ __scopeSheet, ...props }: SheetScopedProps<YStackProps>, forwardedRef) => {\n const context = useSheetContext(SHEET_NAME, __scopeSheet)\n const composedContentRef = useComposedRefs(forwardedRef, context.contentRef)\n return <SheetFrameFrame ref={composedContentRef} {...props} />\n })\n)\n\n// set all the way off screen\nconst HIDDEN_SIZE = 10_000\n\nconst sheetComponents = {\n Handle: SheetHandle,\n Frame: SheetFrame,\n Overlay: SheetOverlay,\n ScrollView: SheetScrollView,\n}\n\nexport const Sheet = withStaticProperties(\n themeable(\n forwardRef<View, SheetProps>(function Sheet(props, ref) {\n const {\n __scopeSheet,\n snapPoints: snapPointsProp = [80],\n open: openProp,\n defaultOpen,\n children: childrenProp,\n position: positionProp,\n onPositionChange,\n onOpenChange,\n defaultPosition,\n dismissOnOverlayPress = true,\n animationConfig,\n dismissOnSnapToBottom = false,\n disableDrag: disableDragProp,\n modal = false,\n handleDisableScroll = true,\n zIndex = 40,\n } = props\n\n if (process.env.NODE_ENV === 'development') {\n if (snapPointsProp.some((p) => p < 0 || p > 100)) {\n // eslint-disable-next-line no-console\n console.warn(\n `\u26A0\uFE0F Invalid snapPoint given, snapPoints must be between 0 and 100, equal to percent height of frame`\n )\n }\n }\n\n const driver = getAnimationDriver()\n if (!driver) {\n throw new Error(`Must set animations in tamagui.config.ts`)\n }\n\n // allows for sheets to be controlled by other components\n const controller = useContext(SheetControllerContext)\n const isHidden = controller?.hidden || false\n const disableDrag = disableDragProp ?? controller?.disableDrag\n const themeName = useThemeName()\n const contentRef = React.useRef<TamaguiElement>(null)\n const scrollBridge = useConstant<ScrollBridge>(() => ({\n enabled: false,\n y: 0,\n paneY: 0,\n paneMinY: 0,\n scrollStartY: -1,\n drag: () => {},\n release: () => {},\n scrollLock: false,\n }))\n\n const onOpenChangeInternal = (val: boolean) => {\n controller?.onOpenChange?.(val)\n onOpenChange?.(val)\n }\n\n const [open, setOpen] = useControllableState({\n prop: controller?.open ?? openProp,\n defaultProp: defaultOpen || true,\n onChange: onOpenChangeInternal,\n strategy: 'most-recent-wins',\n })\n\n const [frameSize, setFrameSize] = useState<number>(0)\n\n const snapPoints = useMemo(\n () => (dismissOnSnapToBottom ? [...snapPointsProp, 0] : snapPointsProp),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(snapPointsProp), dismissOnSnapToBottom]\n )\n\n // lets set -1 to be always the \"open = false\" position\n const [position_, setPosition_] = useControllableState({\n prop: positionProp,\n defaultProp: defaultPosition || (open ? 0 : -1),\n onChange: onPositionChange,\n strategy: 'most-recent-wins',\n })\n const position = open === false ? -1 : position_\n\n // reset position to fully open on re-open after dismissOnSnapToBottom\n if (open && dismissOnSnapToBottom && position === snapPoints.length - 1) {\n setPosition_(0)\n }\n\n const setPosition = useCallback(\n (next: number) => {\n // close on dismissOnSnapToBottom (and set position so it animates)\n if (dismissOnSnapToBottom && next === snapPoints.length - 1) {\n setOpen(false)\n } else {\n setPosition_(next)\n }\n },\n [dismissOnSnapToBottom, snapPoints.length, setPosition_, setOpen]\n )\n\n const animatedNumber = driver.useAnimatedNumber(HIDDEN_SIZE)\n\n // native only fix\n const at = useRef(0)\n driver.useAnimatedNumberReaction(animatedNumber, (value) => {\n at.current = value\n scrollBridge.paneY = value\n })\n\n const [isResizing, setIsResizing] = useState(true)\n useIsomorphicLayoutEffect(() => {\n if (!isResizing) {\n setIsResizing(true)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [modal])\n\n function stopSpring() {\n animatedNumber.stop()\n if (scrollBridge.onFinishAnimate) {\n scrollBridge.onFinishAnimate()\n scrollBridge.onFinishAnimate = undefined\n }\n }\n\n // open must set position\n const shouldSetPositionOpen = open && position < 0\n useEffect(() => {\n if (shouldSetPositionOpen) {\n setPosition(0)\n }\n }, [setPosition, shouldSetPositionOpen])\n\n const positions = useMemo(\n () => snapPoints.map((point) => getPercentSize(point, frameSize)),\n [frameSize, snapPoints]\n )\n\n const animateTo = useEvent((position: number) => {\n const current = animatedNumber.getValue()\n if (isHidden && open) return\n if (!current) return\n if (frameSize === 0) return\n const hiddenValue = frameSize === 0 ? HIDDEN_SIZE : frameSize\n const toValue = isHidden || position === -1 ? hiddenValue : positions[position]\n if (at.current === toValue) return\n stopSpring()\n if (isHidden || isResizing) {\n if (isResizing) {\n setIsResizing(false)\n }\n animatedNumber.setValue(toValue, {\n type: 'timing',\n duration: 0,\n })\n at.current = toValue\n return\n }\n // dont bounce on initial measure to bottom\n const overshootClamping = at.current === HIDDEN_SIZE\n animatedNumber.setValue(toValue, {\n ...animationConfig,\n type: 'spring',\n overshootClamping,\n })\n })\n\n useIsomorphicLayoutEffect(() => {\n animateTo(position)\n }, [isHidden, frameSize, position, animateTo])\n\n const panResponder = useMemo(\n () => {\n if (disableDrag) return\n if (!frameSize) return\n\n const minY = positions[0]\n scrollBridge.paneMinY = minY\n let startY = at.current\n\n function makeUnselectable(val: boolean) {\n if (!selectionStyleSheet) return\n if (!val) {\n selectionStyleSheet.innerText = ``\n } else {\n selectionStyleSheet.innerText = `:root * { user-select: none !important; -webkit-user-select: none !important; }`\n }\n }\n\n const release = ({ vy, dragAt }: { dragAt: number; vy: number }) => {\n isExternalDrag = false\n previouslyScrolling = false\n makeUnselectable(false)\n const at = dragAt + startY\n // seems liky vy goes up to about 4 at the very most (+ is down, - is up)\n // lets base our multiplier on the total layout height\n const end = at + frameSize * vy * 0.2\n let closestPoint = 0\n let dist = Infinity\n for (let i = 0; i < positions.length; i++) {\n const position = positions[i]\n const curDist = end > position ? end - position : position - end\n if (curDist < dist) {\n dist = curDist\n closestPoint = i\n }\n }\n // have to call both because state may not change but need to snap back\n setPosition(closestPoint)\n animateTo(closestPoint)\n }\n\n const finish = (_e: GestureResponderEvent, state: PanResponderGestureState) => {\n release({\n vy: state.vy,\n dragAt: state.dy,\n })\n }\n\n let previouslyScrolling = false\n\n const onMoveShouldSet = (_e: GestureResponderEvent, { dy }: PanResponderGestureState) => {\n const isScrolled = scrollBridge.y !== 0\n if (isScrolled) {\n previouslyScrolling = true\n return false\n }\n if (previouslyScrolling) {\n previouslyScrolling = false\n return true\n }\n const isDraggingUp = dy < 0\n const isAtTop = scrollBridge.paneY <= scrollBridge.paneMinY\n // prevent drag once at top and pulling up\n if (isAtTop) {\n if (!isScrolled && isDraggingUp) {\n return false\n }\n }\n // we could do some detection of other touchables and cancel here..\n return Math.abs(dy) > 8\n }\n\n const grant = () => {\n makeUnselectable(true)\n stopSpring()\n startY = at.current\n }\n\n let isExternalDrag = false\n\n scrollBridge.drag = (dy) => {\n if (!isExternalDrag) {\n isExternalDrag = true\n grant()\n }\n const to = dy + startY\n animatedNumber.setValue(resisted(to, minY), { type: 'direct' })\n }\n\n scrollBridge.release = release\n\n return PanResponder.create({\n onMoveShouldSetPanResponder: onMoveShouldSet,\n onPanResponderGrant: grant,\n onPanResponderMove: (_e, { dy }) => {\n const to = dy + startY\n animatedNumber.setValue(resisted(to, minY), { type: 'direct' })\n },\n onPanResponderEnd: finish,\n onPanResponderTerminate: finish,\n onPanResponderRelease: finish,\n })\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [disableDrag, animateTo, frameSize, positions, setPosition]\n )\n\n let handleComponent: React.ReactElement | null = null\n let overlayComponent: React.ReactElement | null = null\n let frameComponent: React.ReactElement | null = null\n\n // TODO do more radix-like and don't require direct children descendents\n React.Children.forEach(childrenProp, (child) => {\n if (isValidElement(child)) {\n const name = child.type?.['staticConfig']?.componentName\n switch (name) {\n case 'SheetHandle':\n handleComponent = child\n break\n case 'Sheet':\n frameComponent = child\n break\n case 'SheetOverlay':\n overlayComponent = child\n break\n default:\n // eslint-disable-next-line no-console\n console.warn('Warning: passed invalid child to Sheet', child)\n }\n }\n })\n\n const preventShown = controller?.hidden && controller?.open\n\n const animatedStyle = driver.useAnimatedNumberStyle(animatedNumber, (val) => {\n return {\n transform: [{ translateY: frameSize === 0 ? HIDDEN_SIZE : val }],\n }\n })\n\n if (preventShown) {\n return null\n }\n\n // temp until reanimated useAnimatedNumber fix\n const AnimatedView = driver['NumberView'] ?? driver.View\n\n const contents = (\n <SheetProvider\n modal={modal}\n contentRef={contentRef}\n dismissOnOverlayPress={dismissOnOverlayPress}\n dismissOnSnapToBottom={dismissOnSnapToBottom}\n open={open}\n hidden={isHidden}\n scope={__scopeSheet}\n position={position}\n snapPoints={snapPoints}\n setPosition={setPosition}\n setOpen={setOpen}\n scrollBridge={scrollBridge}\n >\n {isResizing ? null : overlayComponent}\n\n <AnimatedView\n ref={ref}\n {...panResponder?.panHandlers}\n onLayout={(e) => {\n const next = e.nativeEvent.layout.height\n setFrameSize((prev) => {\n const isBigChange = Math.abs(prev - next) > 50\n setIsResizing(isBigChange)\n return next\n })\n }}\n pointerEvents={open ? 'auto' : 'none'}\n style={[\n {\n position: 'absolute',\n zIndex,\n width: '100%',\n height: '100%',\n },\n animatedStyle,\n ]}\n >\n {handleComponent}\n\n <RemoveScroll\n enabled={open && modal && handleDisableScroll}\n as={Slot}\n allowPinchZoom\n shards={[contentRef]}\n // causes lots of bugs on touch web on site\n removeScrollBar={false}\n >\n {isResizing ? null : frameComponent}\n </RemoveScroll>\n </AnimatedView>\n </SheetProvider>\n )\n\n if (modal) {\n return (\n <Portal zIndex={zIndex}>\n <Theme name={themeName}>{contents}</Theme>\n </Portal>\n )\n }\n\n return contents\n })\n ),\n sheetComponents\n)\n\nexport const ControlledSheet = Sheet as FunctionComponent<\n Omit<SheetProps, 'open' | 'onOpenChange'> & RefAttributes<View>\n> &\n typeof sheetComponents\n\n/* -------------------------------------------------------------------------------------------------*/\n\nfunction getPercentSize(point?: number, frameSize?: number) {\n if (!frameSize) return 0\n if (point === undefined) {\n // eslint-disable-next-line no-console\n console.warn(`No snapPoint`)\n return 0\n }\n const pct = point / 100\n const next = Math.round(frameSize - pct * frameSize)\n return next\n}\n\nfunction resisted(y: number, minY: number, maxOverflow = 25) {\n if (y < minY) {\n const past = minY - y\n const pctPast = Math.min(maxOverflow, past) / maxOverflow\n const diminishBy = 1.1 - Math.pow(0.1, pctPast)\n const extra = -diminishBy * maxOverflow\n return minY + extra\n }\n return y\n}\n\ntype SheetControllerContextValue = {\n disableDrag?: boolean\n open?: boolean\n // hide without \"closing\" to prevent re-animation when shown again\n hidden?: boolean\n onOpenChange?: React.Dispatch<React.SetStateAction<boolean>> | ((val: boolean) => void)\n}\n\nconst SheetControllerContext = createContext<SheetControllerContextValue | null>(null)\n\nexport const SheetController = ({\n children,\n onOpenChange: onOpenChangeProp,\n ...value\n}: Partial<SheetControllerContextValue> & { children?: React.ReactNode }) => {\n const onOpenChange = useEvent(onOpenChangeProp)\n\n const memoValue = useMemo(\n () => ({\n open: value.open,\n hidden: value.hidden,\n disableDrag: value.disableDrag,\n onOpenChange,\n }),\n [onOpenChange, value.open, value.hidden, value.disableDrag]\n )\n\n return (\n <SheetControllerContext.Provider value={memoValue}>{children}</SheetControllerContext.Provider>\n )\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import { useComposedRefs } from '@tamagui/compose-refs'\nimport {\n GetProps,\n Slot,\n TamaguiElement,\n Theme,\n getAnimationDriver,\n isClient,\n isWeb,\n mergeEvent,\n styled,\n themeable,\n useConstant,\n useEvent,\n useIsomorphicLayoutEffect,\n useThemeName,\n withStaticProperties,\n} from '@tamagui/core'\nimport { Portal } from '@tamagui/portal'\nimport { RemoveScroll } from '@tamagui/remove-scroll'\nimport { XStack, XStackProps, YStack, YStackProps } from '@tamagui/stacks'\nimport { useControllableState } from '@tamagui/use-controllable-state'\nimport React, {\n FunctionComponent,\n RefAttributes,\n createContext,\n forwardRef,\n isValidElement,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport { GestureResponderEvent, PanResponder, PanResponderGestureState, View } from 'react-native'\n\nimport { SHEET_HANDLE_NAME, SHEET_NAME } from './SHEET_HANDLE_NAME'\nimport { SheetProvider, useSheetContext } from './SheetContext'\nimport { SheetScrollView } from './SheetScrollView'\nimport { ScrollBridge, SheetProps, SheetScopedProps } from './types'\n\nexport { createSheetScope } from './SheetContext'\n\n/* -------------------------------------------------------------------------------------------------\n * SheetHandle\n * -----------------------------------------------------------------------------------------------*/\n\nexport const SheetHandleFrame = styled(XStack, {\n name: SHEET_HANDLE_NAME,\n height: 10,\n borderRadius: 100,\n backgroundColor: '$background',\n zIndex: 10,\n marginHorizontal: '35%',\n marginBottom: '$2',\n opacity: 0.5,\n\n hoverStyle: {\n opacity: 0.7,\n },\n\n variants: {\n open: {\n true: {\n pointerEvents: 'auto',\n },\n false: {\n opacity: 0,\n pointerEvents: 'none',\n },\n },\n } as const,\n})\n\nexport const SheetHandle = SheetHandleFrame.extractable(\n ({ __scopeSheet, ...props }: SheetScopedProps<XStackProps>) => {\n const context = useSheetContext(SHEET_HANDLE_NAME, __scopeSheet)\n return (\n <SheetHandleFrame\n onPress={() => {\n // don't toggle to the bottom snap position when dismissOnSnapToBottom set\n const max = context.snapPoints.length + (context.dismissOnSnapToBottom ? -1 : 0)\n const nextPos = (context.position + 1) % max\n context.setPosition(nextPos)\n }}\n open={context.open}\n {...props}\n />\n )\n }\n)\n\n/* -------------------------------------------------------------------------------------------------\n * SheetOverlay\n * -----------------------------------------------------------------------------------------------*/\n\nconst SHEET_OVERLAY_NAME = 'SheetOverlay'\n\nexport const SheetOverlayFrame = styled(YStack, {\n name: SHEET_OVERLAY_NAME,\n // TODO this should be $background without opacity and just customized by theme\n backgroundColor: '$color',\n fullscreen: true,\n opacity: 0.2,\n zIndex: 0,\n\n variants: {\n closed: {\n true: {\n opacity: 0,\n pointerEvents: 'none',\n },\n false: {\n pointerEvents: 'auto',\n },\n },\n } as const,\n})\n\nexport type SheetOverlayProps = GetProps<typeof SheetOverlayFrame>\n\nexport const SheetOverlay = SheetOverlayFrame.extractable(\n ({ __scopeSheet, ...props }: SheetScopedProps<SheetOverlayProps>) => {\n const context = useSheetContext(SHEET_OVERLAY_NAME, __scopeSheet)\n return (\n <SheetOverlayFrame\n closed={!context.open || context.hidden}\n {...props}\n onPress={mergeEvent(\n props.onPress,\n context.dismissOnOverlayPress\n ? () => {\n context.setOpen(false)\n }\n : undefined\n )}\n />\n )\n }\n)\n\n/* -------------------------------------------------------------------------------------------------\n * Sheet\n * -----------------------------------------------------------------------------------------------*/\n\nconst selectionStyleSheet = isClient ? document.createElement('style') : null\nif (selectionStyleSheet) {\n document.head.appendChild(selectionStyleSheet)\n}\n\nexport const SheetFrameFrame = styled(YStack, {\n name: SHEET_NAME,\n flex: 1,\n backgroundColor: '$background',\n borderTopLeftRadius: '$4',\n borderTopRightRadius: '$4',\n width: '100%',\n maxHeight: '100%',\n overflow: 'hidden',\n pointerEvents: 'auto',\n})\n\nexport const SheetFrame = SheetFrameFrame.extractable(\n forwardRef(({ __scopeSheet, ...props }: SheetScopedProps<YStackProps>, forwardedRef) => {\n const context = useSheetContext(SHEET_NAME, __scopeSheet)\n const composedContentRef = useComposedRefs(forwardedRef, context.contentRef)\n return <SheetFrameFrame ref={composedContentRef} {...props} />\n })\n)\n\n// set all the way off screen\nconst HIDDEN_SIZE = 10_000\n\nconst sheetComponents = {\n Handle: SheetHandle,\n Frame: SheetFrame,\n Overlay: SheetOverlay,\n ScrollView: SheetScrollView,\n}\n\nexport const Sheet = withStaticProperties(\n themeable(\n forwardRef<View, SheetProps>(function Sheet(props, ref) {\n const {\n __scopeSheet,\n snapPoints: snapPointsProp = [80],\n open: openProp,\n defaultOpen,\n children: childrenProp,\n position: positionProp,\n onPositionChange,\n onOpenChange,\n defaultPosition,\n dismissOnOverlayPress = true,\n animationConfig,\n dismissOnSnapToBottom = false,\n disableDrag: disableDragProp,\n modal = false,\n handleDisableScroll = true,\n zIndex = 40,\n } = props\n\n if (process.env.NODE_ENV === 'development') {\n if (snapPointsProp.some((p) => p < 0 || p > 100)) {\n // eslint-disable-next-line no-console\n console.warn(\n `\u26A0\uFE0F Invalid snapPoint given, snapPoints must be between 0 and 100, equal to percent height of frame`\n )\n }\n }\n\n const driver = getAnimationDriver()\n if (!driver) {\n throw new Error(`Must set animations in tamagui.config.ts`)\n }\n\n // allows for sheets to be controlled by other components\n const controller = useContext(SheetControllerContext)\n const isHidden = controller?.hidden || false\n const disableDrag = disableDragProp ?? controller?.disableDrag\n const themeName = useThemeName()\n const contentRef = React.useRef<TamaguiElement>(null)\n const scrollBridge = useConstant<ScrollBridge>(() => ({\n enabled: false,\n y: 0,\n paneY: 0,\n paneMinY: 0,\n scrollStartY: -1,\n drag: () => {},\n release: () => {},\n scrollLock: false,\n }))\n\n const onOpenChangeInternal = (val: boolean) => {\n controller?.onOpenChange?.(val)\n onOpenChange?.(val)\n }\n\n const [open, setOpen] = useControllableState({\n prop: controller?.open ?? openProp,\n defaultProp: defaultOpen || true,\n onChange: onOpenChangeInternal,\n strategy: 'most-recent-wins',\n })\n\n const [frameSize, setFrameSize] = useState<number>(0)\n\n const snapPoints = useMemo(\n () => (dismissOnSnapToBottom ? [...snapPointsProp, 0] : snapPointsProp),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(snapPointsProp), dismissOnSnapToBottom]\n )\n\n // lets set -1 to be always the \"open = false\" position\n const [position_, setPosition_] = useControllableState({\n prop: positionProp,\n defaultProp: defaultPosition || (open ? 0 : -1),\n onChange: onPositionChange,\n strategy: 'most-recent-wins',\n })\n const position = open === false ? -1 : position_\n\n // reset position to fully open on re-open after dismissOnSnapToBottom\n if (open && dismissOnSnapToBottom && position === snapPoints.length - 1) {\n setPosition_(0)\n }\n\n const setPosition = useCallback(\n (next: number) => {\n // close on dismissOnSnapToBottom (and set position so it animates)\n if (dismissOnSnapToBottom && next === snapPoints.length - 1) {\n setOpen(false)\n } else {\n setPosition_(next)\n }\n },\n [dismissOnSnapToBottom, snapPoints.length, setPosition_, setOpen]\n )\n\n const animatedNumber = driver.useAnimatedNumber(HIDDEN_SIZE)\n\n // native only fix\n const at = useRef(0)\n driver.useAnimatedNumberReaction(animatedNumber, (value) => {\n at.current = value\n scrollBridge.paneY = value\n })\n\n const [isResizing, setIsResizing] = useState(true)\n useIsomorphicLayoutEffect(() => {\n if (!isResizing) {\n setIsResizing(true)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [modal])\n\n function stopSpring() {\n animatedNumber.stop()\n if (scrollBridge.onFinishAnimate) {\n scrollBridge.onFinishAnimate()\n scrollBridge.onFinishAnimate = undefined\n }\n }\n\n // open must set position\n const shouldSetPositionOpen = open && position < 0\n useEffect(() => {\n if (shouldSetPositionOpen) {\n setPosition(0)\n }\n }, [setPosition, shouldSetPositionOpen])\n\n const positions = useMemo(\n () => snapPoints.map((point) => getPercentSize(point, frameSize)),\n [frameSize, snapPoints]\n )\n\n const animateTo = useEvent((position: number) => {\n const current = animatedNumber.getValue()\n if (isHidden && open) return\n if (!current) return\n if (frameSize === 0) return\n const hiddenValue = frameSize === 0 ? HIDDEN_SIZE : frameSize\n const toValue = isHidden || position === -1 ? hiddenValue : positions[position]\n if (at.current === toValue) return\n stopSpring()\n if (isHidden || isResizing) {\n if (isResizing) {\n setIsResizing(false)\n }\n animatedNumber.setValue(toValue, {\n type: 'timing',\n duration: 0,\n })\n at.current = toValue\n return\n }\n // dont bounce on initial measure to bottom\n const overshootClamping = at.current === HIDDEN_SIZE\n animatedNumber.setValue(toValue, {\n ...animationConfig,\n type: 'spring',\n overshootClamping,\n })\n })\n\n useIsomorphicLayoutEffect(() => {\n animateTo(position)\n }, [isHidden, frameSize, position, animateTo])\n\n const panResponder = useMemo(\n () => {\n if (disableDrag) return\n if (!frameSize) return\n\n const minY = positions[0]\n scrollBridge.paneMinY = minY\n let startY = at.current\n\n function makeUnselectable(val: boolean) {\n if (!selectionStyleSheet) return\n if (!val) {\n selectionStyleSheet.innerText = ``\n } else {\n selectionStyleSheet.innerText = `:root * { user-select: none !important; -webkit-user-select: none !important; }`\n }\n }\n\n const release = ({ vy, dragAt }: { dragAt: number; vy: number }) => {\n isExternalDrag = false\n previouslyScrolling = false\n makeUnselectable(false)\n const at = dragAt + startY\n // seems liky vy goes up to about 4 at the very most (+ is down, - is up)\n // lets base our multiplier on the total layout height\n const end = at + frameSize * vy * 0.2\n let closestPoint = 0\n let dist = Infinity\n for (let i = 0; i < positions.length; i++) {\n const position = positions[i]\n const curDist = end > position ? end - position : position - end\n if (curDist < dist) {\n dist = curDist\n closestPoint = i\n }\n }\n // have to call both because state may not change but need to snap back\n setPosition(closestPoint)\n animateTo(closestPoint)\n }\n\n const finish = (_e: GestureResponderEvent, state: PanResponderGestureState) => {\n release({\n vy: state.vy,\n dragAt: state.dy,\n })\n }\n\n let previouslyScrolling = false\n\n const onMoveShouldSet = (_e: GestureResponderEvent, { dy }: PanResponderGestureState) => {\n const isScrolled = scrollBridge.y !== 0\n if (isScrolled) {\n previouslyScrolling = true\n return false\n }\n if (previouslyScrolling) {\n previouslyScrolling = false\n return true\n }\n const isDraggingUp = dy < 0\n const isAtTop = scrollBridge.paneY <= scrollBridge.paneMinY\n // prevent drag once at top and pulling up\n if (isAtTop) {\n if (!isScrolled && isDraggingUp) {\n return false\n }\n }\n // we could do some detection of other touchables and cancel here..\n return Math.abs(dy) > 8\n }\n\n const grant = () => {\n makeUnselectable(true)\n stopSpring()\n startY = at.current\n }\n\n let isExternalDrag = false\n\n scrollBridge.drag = (dy) => {\n if (!isExternalDrag) {\n isExternalDrag = true\n grant()\n }\n const to = dy + startY\n animatedNumber.setValue(resisted(to, minY), { type: 'direct' })\n }\n\n scrollBridge.release = release\n\n return PanResponder.create({\n onMoveShouldSetPanResponder: onMoveShouldSet,\n onPanResponderGrant: grant,\n onPanResponderMove: (_e, { dy }) => {\n const toFull = dy + startY\n const to = resisted(toFull, minY)\n animatedNumber.setValue(to, { type: 'direct' })\n },\n onPanResponderEnd: finish,\n onPanResponderTerminate: finish,\n onPanResponderRelease: finish,\n })\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [disableDrag, animateTo, frameSize, positions, setPosition]\n )\n\n let handleComponent: React.ReactElement | null = null\n let overlayComponent: React.ReactElement | null = null\n let frameComponent: React.ReactElement | null = null\n\n // TODO do more radix-like and don't require direct children descendents\n React.Children.forEach(childrenProp, (child) => {\n if (isValidElement(child)) {\n const name = child.type?.['staticConfig']?.componentName\n switch (name) {\n case 'SheetHandle':\n handleComponent = child\n break\n case 'Sheet':\n frameComponent = child\n break\n case 'SheetOverlay':\n overlayComponent = child\n break\n default:\n // eslint-disable-next-line no-console\n console.warn('Warning: passed invalid child to Sheet', child)\n }\n }\n })\n\n const preventShown = controller?.hidden && controller?.open\n\n const animatedStyle = driver.useAnimatedNumberStyle(animatedNumber, (val) => {\n return {\n transform: [{ translateY: frameSize === 0 ? HIDDEN_SIZE : val }],\n }\n })\n\n if (preventShown) {\n return null\n }\n\n // temp until reanimated useAnimatedNumber fix\n const AnimatedView = driver['NumberView'] ?? driver.View\n\n /**\n * This is a hacky workaround for native:\n */\n const [isShowingInnerSheet, setIsShowingInnerSheet] = useState(false)\n const shouldHideParentSheet = !isWeb && modal && isShowingInnerSheet\n const parentSheetContext = useContext(SheetInsideSheetContext)\n const onInnerSheet = useCallback((hasChild: boolean) => {\n setIsShowingInnerSheet(hasChild)\n }, [])\n useIsomorphicLayoutEffect(() => {\n if (!parentSheetContext || !open) return\n parentSheetContext(true)\n return () => {\n parentSheetContext(false)\n }\n }, [parentSheetContext, open])\n\n const contents = (\n <SheetProvider\n modal={modal}\n contentRef={contentRef}\n dismissOnOverlayPress={dismissOnOverlayPress}\n dismissOnSnapToBottom={dismissOnSnapToBottom}\n open={open}\n hidden={isHidden}\n scope={__scopeSheet}\n position={position}\n snapPoints={snapPoints}\n setPosition={setPosition}\n setOpen={setOpen}\n scrollBridge={scrollBridge}\n >\n {isResizing || shouldHideParentSheet ? null : overlayComponent}\n\n <AnimatedView\n ref={ref}\n {...panResponder?.panHandlers}\n onLayout={(e) => {\n const next = e.nativeEvent.layout.height\n setFrameSize((prev) => {\n const isBigChange = Math.abs(prev - next) > 50\n setIsResizing(isBigChange)\n return next\n })\n }}\n pointerEvents={open && !shouldHideParentSheet ? 'auto' : 'none'}\n style={[\n {\n position: 'absolute',\n zIndex,\n width: '100%',\n height: '100%',\n opacity: shouldHideParentSheet ? 0 : 1,\n },\n animatedStyle,\n ]}\n >\n {handleComponent}\n\n <RemoveScroll\n enabled={open && modal && handleDisableScroll}\n as={Slot}\n allowPinchZoom\n shards={[contentRef]}\n // causes lots of bugs on touch web on site\n removeScrollBar={false}\n >\n {isResizing ? null : frameComponent}\n </RemoveScroll>\n </AnimatedView>\n </SheetProvider>\n )\n\n if (modal) {\n const modalContents = (\n <Portal zIndex={zIndex}>\n <Theme name={themeName}>{contents}</Theme>\n </Portal>\n )\n\n if (isWeb) {\n return modalContents\n }\n\n // on native we don't support multiple modals yet... fix for now is to hide outer one\n return (\n <SheetInsideSheetContext.Provider value={onInnerSheet}>\n {modalContents}\n </SheetInsideSheetContext.Provider>\n )\n }\n\n return contents\n })\n ),\n sheetComponents\n)\n\nconst SheetInsideSheetContext = createContext<((hasChild: boolean) => void) | null>(null)\n\nexport const ControlledSheet = Sheet as FunctionComponent<\n Omit<SheetProps, 'open' | 'onOpenChange'> & RefAttributes<View>\n> &\n typeof sheetComponents\n\n/* -------------------------------------------------------------------------------------------------*/\n\nfunction getPercentSize(point?: number, frameSize?: number) {\n if (!frameSize) return 0\n if (point === undefined) {\n // eslint-disable-next-line no-console\n console.warn(`No snapPoint`)\n return 0\n }\n const pct = point / 100\n const next = Math.round(frameSize - pct * frameSize)\n return next\n}\n\nfunction resisted(y: number, minY: number, maxOverflow = 25) {\n if (y < minY) {\n const past = minY - y\n const pctPast = Math.min(maxOverflow, past) / maxOverflow\n const diminishBy = 1.1 - Math.pow(0.1, pctPast)\n const extra = -diminishBy * maxOverflow\n return minY + extra\n }\n return y\n}\n\ntype SheetControllerContextValue = {\n disableDrag?: boolean\n open?: boolean\n // hide without \"closing\" to prevent re-animation when shown again\n hidden?: boolean\n onOpenChange?: React.Dispatch<React.SetStateAction<boolean>> | ((val: boolean) => void)\n}\n\nconst SheetControllerContext = createContext<SheetControllerContextValue | null>(null)\n\nexport const SheetController = ({\n children,\n onOpenChange: onOpenChangeProp,\n ...value\n}: Partial<SheetControllerContextValue> & { children?: React.ReactNode }) => {\n const onOpenChange = useEvent(onOpenChangeProp)\n\n const memoValue = useMemo(\n () => ({\n open: value.open,\n hidden: value.hidden,\n disableDrag: value.disableDrag,\n onOpenChange,\n }),\n [onOpenChange, value.open, value.hidden, value.disableDrag]\n )\n\n return (\n <SheetControllerContext.Provider value={memoValue}>{children}</SheetControllerContext.Provider>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["Sheet", "position", "at"]
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/SheetScrollView.tsx"],
|
|
4
|
-
"sourcesContent": ["import { TamaguiElement } from '@tamagui/core'\nimport { ScrollView, ScrollViewProps } from '@tamagui/scroll-view'\nimport { forwardRef, useRef, useState } from 'react'\n\nimport { useSheetContext } from './SheetContext'\nimport { SheetScopedProps } from './types'\n\n/* -------------------------------------------------------------------------------------------------\n * SheetScrollView\n * -----------------------------------------------------------------------------------------------*/\n\nconst SHEET_SCROLL_VIEW_NAME = 'SheetScrollView'\n\nexport const SheetScrollView = forwardRef<TamaguiElement, ScrollViewProps>(\n ({ __scopeSheet, ...props }: SheetScopedProps<ScrollViewProps>, ref) => {\n const { scrollBridge } = useSheetContext(SHEET_SCROLL_VIEW_NAME, __scopeSheet)\n const [scrollEnabled, setScrollEnabled] = useState(true)\n const state = useRef({\n lastPageY: 0,\n dragAt: 0,\n dys: [] as number[], // store a few recent dys to get velocity on release\n isScrolling: false,\n })\n\n const release = () => {\n scrollBridge.scrollStartY = -1\n state.current.isScrolling = false\n setScrollEnabled(true)\n let vy = 0\n if (state.current.dys.length) {\n const recentDys = state.current.dys.slice(-10)\n const dist = recentDys.length ? recentDys.reduce((a, b) => a + b, 0) : 0\n const avgDy = dist / recentDys.length\n vy = avgDy * 0.04\n }\n state.current.dys = []\n scrollBridge.release({\n dragAt: state.current.dragAt,\n vy,\n })\n }\n\n return (\n <ScrollView\n ref={ref}\n flex={1}\n scrollEventThrottle={8}\n scrollEnabled={scrollEnabled}\n onScroll={(e) => {\n const { y } = e.nativeEvent.contentOffset\n scrollBridge.y = y\n if (y > 0) {\n scrollBridge.scrollStartY = -1\n }\n }}\n onStartShouldSetResponder={() => {\n scrollBridge.scrollStartY = -1\n return true\n }}\n onMoveShouldSetResponder={() => true}\n onResponderMove={(e) => {\n const { pageY } = e.nativeEvent\n\n if (state.current.isScrolling) {\n return\n }\n\n if (scrollBridge.scrollStartY === -1) {\n scrollBridge.scrollStartY = pageY\n state.current.lastPageY = pageY\n }\n\n const dragAt = pageY - scrollBridge.scrollStartY\n const dy = pageY - state.current.lastPageY\n state.current.lastPageY = pageY // after dy\n
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import { TamaguiElement } from '@tamagui/core'\nimport { ScrollView, ScrollViewProps } from '@tamagui/scroll-view'\nimport { forwardRef, useRef, useState } from 'react'\n\nimport { useSheetContext } from './SheetContext'\nimport { SheetScopedProps } from './types'\n\n// TODO ideally would replicate https://github.com/ammarahm-ed/react-native-actions-sheet/blob/master/src/index.tsx\n\n/* -------------------------------------------------------------------------------------------------\n * SheetScrollView\n * -----------------------------------------------------------------------------------------------*/\n\nconst SHEET_SCROLL_VIEW_NAME = 'SheetScrollView'\n\nexport const SheetScrollView = forwardRef<TamaguiElement, ScrollViewProps>(\n ({ __scopeSheet, ...props }: SheetScopedProps<ScrollViewProps>, ref) => {\n const { scrollBridge } = useSheetContext(SHEET_SCROLL_VIEW_NAME, __scopeSheet)\n const [scrollEnabled, setScrollEnabled] = useState(true)\n const state = useRef({\n lastPageY: 0,\n dragAt: 0,\n dys: [] as number[], // store a few recent dys to get velocity on release\n isScrolling: false,\n })\n\n const release = () => {\n scrollBridge.scrollStartY = -1\n state.current.isScrolling = false\n setScrollEnabled(true)\n let vy = 0\n if (state.current.dys.length) {\n const recentDys = state.current.dys.slice(-10)\n const dist = recentDys.length ? recentDys.reduce((a, b) => a + b, 0) : 0\n const avgDy = dist / recentDys.length\n vy = avgDy * 0.04\n }\n state.current.dys = []\n scrollBridge.release({\n dragAt: state.current.dragAt,\n vy,\n })\n }\n\n return (\n <ScrollView\n ref={ref}\n flex={1}\n scrollEventThrottle={8}\n scrollEnabled={scrollEnabled}\n onScroll={(e) => {\n const { y } = e.nativeEvent.contentOffset\n scrollBridge.y = y\n if (y > 0) {\n scrollBridge.scrollStartY = -1\n }\n }}\n onStartShouldSetResponder={() => {\n scrollBridge.scrollStartY = -1\n return true\n }}\n onMoveShouldSetResponder={() => true}\n onResponderMove={(e) => {\n const { pageY } = e.nativeEvent\n\n if (state.current.isScrolling) {\n return\n }\n\n if (scrollBridge.scrollStartY === -1) {\n scrollBridge.scrollStartY = pageY\n state.current.lastPageY = pageY\n }\n\n const dragAt = pageY - scrollBridge.scrollStartY\n const dy = pageY - state.current.lastPageY\n state.current.lastPageY = pageY // after dy\n const isDraggingUp = dy < 0\n const isPaneAtTop = scrollBridge.paneY <= scrollBridge.paneMinY\n\n if ((dy === 0 || isDraggingUp) && isPaneAtTop) {\n state.current.isScrolling = true\n setScrollEnabled(true)\n return\n }\n\n setScrollEnabled(false)\n scrollBridge.drag(dragAt)\n state.current.dragAt = dragAt\n state.current.dys.push(dy)\n // only do every so often, cut down to 10 again\n if (state.current.dys.length > 100) {\n state.current.dys = state.current.dys.slice(-10)\n }\n }}\n onResponderRelease={release}\n {...props}\n />\n )\n }\n)\n"],
|
|
5
|
+
"mappings": "AA6CM;AA5CN,SAAS,kBAAmC;AAC5C,SAAS,YAAY,QAAQ,gBAAgB;AAE7C,SAAS,uBAAuB;AAShC,MAAM,yBAAyB;AAExB,MAAM,kBAAkB;AAAA,EAC7B,CAAC,EAAE,iBAAiB,MAAM,GAAsC,QAAQ;AACtE,UAAM,EAAE,aAAa,IAAI,gBAAgB,wBAAwB,YAAY;AAC7E,UAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,IAAI;AACvD,UAAM,QAAQ,OAAO;AAAA,MACnB,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,KAAK,CAAC;AAAA,MACN,aAAa;AAAA,IACf,CAAC;AAED,UAAM,UAAU,MAAM;AACpB,mBAAa,eAAe;AAC5B,YAAM,QAAQ,cAAc;AAC5B,uBAAiB,IAAI;AACrB,UAAI,KAAK;AACT,UAAI,MAAM,QAAQ,IAAI,QAAQ;AAC5B,cAAM,YAAY,MAAM,QAAQ,IAAI,MAAM,GAAG;AAC7C,cAAM,OAAO,UAAU,SAAS,UAAU,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI;AACvE,cAAM,QAAQ,OAAO,UAAU;AAC/B,aAAK,QAAQ;AAAA,MACf;AACA,YAAM,QAAQ,MAAM,CAAC;AACrB,mBAAa,QAAQ;AAAA,QACnB,QAAQ,MAAM,QAAQ;AAAA,QACtB;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WACE,oBAAC;AAAA,MACC;AAAA,MACA,MAAM;AAAA,MACN,qBAAqB;AAAA,MACrB;AAAA,MACA,UAAU,CAAC,MAAM;AACf,cAAM,EAAE,EAAE,IAAI,EAAE,YAAY;AAC5B,qBAAa,IAAI;AACjB,YAAI,IAAI,GAAG;AACT,uBAAa,eAAe;AAAA,QAC9B;AAAA,MACF;AAAA,MACA,2BAA2B,MAAM;AAC/B,qBAAa,eAAe;AAC5B,eAAO;AAAA,MACT;AAAA,MACA,0BAA0B,MAAM;AAAA,MAChC,iBAAiB,CAAC,MAAM;AACtB,cAAM,EAAE,MAAM,IAAI,EAAE;AAEpB,YAAI,MAAM,QAAQ,aAAa;AAC7B;AAAA,QACF;AAEA,YAAI,aAAa,iBAAiB,IAAI;AACpC,uBAAa,eAAe;AAC5B,gBAAM,QAAQ,YAAY;AAAA,QAC5B;AAEA,cAAM,SAAS,QAAQ,aAAa;AACpC,cAAM,KAAK,QAAQ,MAAM,QAAQ;AACjC,cAAM,QAAQ,YAAY;AAC1B,cAAM,eAAe,KAAK;AAC1B,cAAM,cAAc,aAAa,SAAS,aAAa;AAEvD,aAAK,OAAO,KAAK,iBAAiB,aAAa;AAC7C,gBAAM,QAAQ,cAAc;AAC5B,2BAAiB,IAAI;AACrB;AAAA,QACF;AAEA,yBAAiB,KAAK;AACtB,qBAAa,KAAK,MAAM;AACxB,cAAM,QAAQ,SAAS;AACvB,cAAM,QAAQ,IAAI,KAAK,EAAE;AAEzB,YAAI,MAAM,QAAQ,IAAI,SAAS,KAAK;AAClC,gBAAM,QAAQ,MAAM,MAAM,QAAQ,IAAI,MAAM,GAAG;AAAA,QACjD;AAAA,MACF;AAAA,MACA,oBAAoB;AAAA,MACnB,GAAG;AAAA,KACN;AAAA,EAEJ;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/jsx/Sheet.js
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
Theme,
|
|
5
5
|
getAnimationDriver,
|
|
6
6
|
isClient,
|
|
7
|
+
isWeb,
|
|
7
8
|
mergeEvent,
|
|
8
9
|
styled,
|
|
9
10
|
themeable,
|
|
@@ -355,8 +356,9 @@ const Sheet = withStaticProperties(
|
|
|
355
356
|
onMoveShouldSetPanResponder: onMoveShouldSet,
|
|
356
357
|
onPanResponderGrant: grant,
|
|
357
358
|
onPanResponderMove: (_e, { dy }) => {
|
|
358
|
-
const
|
|
359
|
-
|
|
359
|
+
const toFull = dy + startY;
|
|
360
|
+
const to = resisted(toFull, minY);
|
|
361
|
+
animatedNumber.setValue(to, { type: "direct" });
|
|
360
362
|
},
|
|
361
363
|
onPanResponderEnd: finish,
|
|
362
364
|
onPanResponderTerminate: finish,
|
|
@@ -396,8 +398,22 @@ const Sheet = withStaticProperties(
|
|
|
396
398
|
return null;
|
|
397
399
|
}
|
|
398
400
|
const AnimatedView = driver["NumberView"] ?? driver.View;
|
|
401
|
+
const [isShowingInnerSheet, setIsShowingInnerSheet] = useState(false);
|
|
402
|
+
const shouldHideParentSheet = !isWeb && modal && isShowingInnerSheet;
|
|
403
|
+
const parentSheetContext = useContext(SheetInsideSheetContext);
|
|
404
|
+
const onInnerSheet = useCallback((hasChild) => {
|
|
405
|
+
setIsShowingInnerSheet(hasChild);
|
|
406
|
+
}, []);
|
|
407
|
+
useIsomorphicLayoutEffect(() => {
|
|
408
|
+
if (!parentSheetContext || !open)
|
|
409
|
+
return;
|
|
410
|
+
parentSheetContext(true);
|
|
411
|
+
return () => {
|
|
412
|
+
parentSheetContext(false);
|
|
413
|
+
};
|
|
414
|
+
}, [parentSheetContext, open]);
|
|
399
415
|
const contents = <SheetProvider modal={modal} contentRef={contentRef} dismissOnOverlayPress={dismissOnOverlayPress} dismissOnSnapToBottom={dismissOnSnapToBottom} open={open} hidden={isHidden} scope={__scopeSheet} position={position} snapPoints={snapPoints} setPosition={setPosition} setOpen={setOpen} scrollBridge={scrollBridge}>
|
|
400
|
-
{isResizing ? null : overlayComponent}
|
|
416
|
+
{isResizing || shouldHideParentSheet ? null : overlayComponent}
|
|
401
417
|
<AnimatedView ref={ref} {...panResponder?.panHandlers} onLayout={(e) => {
|
|
402
418
|
const next = e.nativeEvent.layout.height;
|
|
403
419
|
setFrameSize((prev) => {
|
|
@@ -405,12 +421,13 @@ const Sheet = withStaticProperties(
|
|
|
405
421
|
setIsResizing(isBigChange);
|
|
406
422
|
return next;
|
|
407
423
|
});
|
|
408
|
-
}} pointerEvents={open ? "auto" : "none"} style={[
|
|
424
|
+
}} pointerEvents={open && !shouldHideParentSheet ? "auto" : "none"} style={[
|
|
409
425
|
{
|
|
410
426
|
position: "absolute",
|
|
411
427
|
zIndex,
|
|
412
428
|
width: "100%",
|
|
413
|
-
height: "100%"
|
|
429
|
+
height: "100%",
|
|
430
|
+
opacity: shouldHideParentSheet ? 0 : 1
|
|
414
431
|
},
|
|
415
432
|
animatedStyle
|
|
416
433
|
]}>
|
|
@@ -419,13 +436,18 @@ const Sheet = withStaticProperties(
|
|
|
419
436
|
</AnimatedView>
|
|
420
437
|
</SheetProvider>;
|
|
421
438
|
if (modal) {
|
|
422
|
-
|
|
439
|
+
const modalContents = <Portal zIndex={zIndex}><Theme name={themeName}>{contents}</Theme></Portal>;
|
|
440
|
+
if (isWeb) {
|
|
441
|
+
return modalContents;
|
|
442
|
+
}
|
|
443
|
+
return <SheetInsideSheetContext.Provider value={onInnerSheet}>{modalContents}</SheetInsideSheetContext.Provider>;
|
|
423
444
|
}
|
|
424
445
|
return contents;
|
|
425
446
|
})
|
|
426
447
|
),
|
|
427
448
|
sheetComponents
|
|
428
449
|
);
|
|
450
|
+
const SheetInsideSheetContext = createContext(null);
|
|
429
451
|
const ControlledSheet = Sheet;
|
|
430
452
|
function getPercentSize(point, frameSize) {
|
|
431
453
|
if (!frameSize)
|
package/dist/jsx/Sheet.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/Sheet.tsx"],
|
|
4
|
-
"sourcesContent": ["import { useComposedRefs } from '@tamagui/compose-refs'\nimport {\n GetProps,\n Slot,\n TamaguiElement,\n Theme,\n getAnimationDriver,\n isClient,\n mergeEvent,\n styled,\n themeable,\n useConstant,\n useEvent,\n useIsomorphicLayoutEffect,\n useThemeName,\n withStaticProperties,\n} from '@tamagui/core'\nimport { Portal } from '@tamagui/portal'\nimport { RemoveScroll } from '@tamagui/remove-scroll'\nimport { XStack, XStackProps, YStack, YStackProps } from '@tamagui/stacks'\nimport { useControllableState } from '@tamagui/use-controllable-state'\nimport React, {\n FunctionComponent,\n RefAttributes,\n createContext,\n forwardRef,\n isValidElement,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport { GestureResponderEvent, PanResponder, PanResponderGestureState, View } from 'react-native'\n\nimport { SHEET_HANDLE_NAME, SHEET_NAME } from './SHEET_HANDLE_NAME'\nimport { SheetProvider, useSheetContext } from './SheetContext'\nimport { SheetScrollView } from './SheetScrollView'\nimport { ScrollBridge, SheetProps, SheetScopedProps } from './types'\n\nexport { createSheetScope } from './SheetContext'\n\n/* -------------------------------------------------------------------------------------------------\n * SheetHandle\n * -----------------------------------------------------------------------------------------------*/\n\nexport const SheetHandleFrame = styled(XStack, {\n name: SHEET_HANDLE_NAME,\n height: 10,\n borderRadius: 100,\n backgroundColor: '$background',\n zIndex: 10,\n marginHorizontal: '35%',\n marginBottom: '$2',\n opacity: 0.5,\n\n hoverStyle: {\n opacity: 0.7,\n },\n\n variants: {\n open: {\n true: {\n pointerEvents: 'auto',\n },\n false: {\n opacity: 0,\n pointerEvents: 'none',\n },\n },\n } as const,\n})\n\nexport const SheetHandle = SheetHandleFrame.extractable(\n ({ __scopeSheet, ...props }: SheetScopedProps<XStackProps>) => {\n const context = useSheetContext(SHEET_HANDLE_NAME, __scopeSheet)\n return (\n <SheetHandleFrame\n onPress={() => {\n // don't toggle to the bottom snap position when dismissOnSnapToBottom set\n const max = context.snapPoints.length + (context.dismissOnSnapToBottom ? -1 : 0)\n const nextPos = (context.position + 1) % max\n context.setPosition(nextPos)\n }}\n open={context.open}\n {...props}\n />\n )\n }\n)\n\n/* -------------------------------------------------------------------------------------------------\n * SheetOverlay\n * -----------------------------------------------------------------------------------------------*/\n\nconst SHEET_OVERLAY_NAME = 'SheetOverlay'\n\nexport const SheetOverlayFrame = styled(YStack, {\n name: SHEET_OVERLAY_NAME,\n // TODO this should be $background without opacity and just customized by theme\n backgroundColor: '$color',\n fullscreen: true,\n opacity: 0.2,\n zIndex: 0,\n\n variants: {\n closed: {\n true: {\n opacity: 0,\n pointerEvents: 'none',\n },\n false: {\n pointerEvents: 'auto',\n },\n },\n } as const,\n})\n\nexport type SheetOverlayProps = GetProps<typeof SheetOverlayFrame>\n\nexport const SheetOverlay = SheetOverlayFrame.extractable(\n ({ __scopeSheet, ...props }: SheetScopedProps<SheetOverlayProps>) => {\n const context = useSheetContext(SHEET_OVERLAY_NAME, __scopeSheet)\n return (\n <SheetOverlayFrame\n closed={!context.open || context.hidden}\n {...props}\n onPress={mergeEvent(\n props.onPress,\n context.dismissOnOverlayPress\n ? () => {\n context.setOpen(false)\n }\n : undefined\n )}\n />\n )\n }\n)\n\n/* -------------------------------------------------------------------------------------------------\n * Sheet\n * -----------------------------------------------------------------------------------------------*/\n\nconst selectionStyleSheet = isClient ? document.createElement('style') : null\nif (selectionStyleSheet) {\n document.head.appendChild(selectionStyleSheet)\n}\n\nexport const SheetFrameFrame = styled(YStack, {\n name: SHEET_NAME,\n flex: 1,\n backgroundColor: '$background',\n borderTopLeftRadius: '$4',\n borderTopRightRadius: '$4',\n width: '100%',\n maxHeight: '100%',\n overflow: 'hidden',\n pointerEvents: 'auto',\n})\n\nexport const SheetFrame = SheetFrameFrame.extractable(\n forwardRef(({ __scopeSheet, ...props }: SheetScopedProps<YStackProps>, forwardedRef) => {\n const context = useSheetContext(SHEET_NAME, __scopeSheet)\n const composedContentRef = useComposedRefs(forwardedRef, context.contentRef)\n return <SheetFrameFrame ref={composedContentRef} {...props} />\n })\n)\n\n// set all the way off screen\nconst HIDDEN_SIZE = 10_000\n\nconst sheetComponents = {\n Handle: SheetHandle,\n Frame: SheetFrame,\n Overlay: SheetOverlay,\n ScrollView: SheetScrollView,\n}\n\nexport const Sheet = withStaticProperties(\n themeable(\n forwardRef<View, SheetProps>(function Sheet(props, ref) {\n const {\n __scopeSheet,\n snapPoints: snapPointsProp = [80],\n open: openProp,\n defaultOpen,\n children: childrenProp,\n position: positionProp,\n onPositionChange,\n onOpenChange,\n defaultPosition,\n dismissOnOverlayPress = true,\n animationConfig,\n dismissOnSnapToBottom = false,\n disableDrag: disableDragProp,\n modal = false,\n handleDisableScroll = true,\n zIndex = 40,\n } = props\n\n if (process.env.NODE_ENV === 'development') {\n if (snapPointsProp.some((p) => p < 0 || p > 100)) {\n // eslint-disable-next-line no-console\n console.warn(\n `\u26A0\uFE0F Invalid snapPoint given, snapPoints must be between 0 and 100, equal to percent height of frame`\n )\n }\n }\n\n const driver = getAnimationDriver()\n if (!driver) {\n throw new Error(`Must set animations in tamagui.config.ts`)\n }\n\n // allows for sheets to be controlled by other components\n const controller = useContext(SheetControllerContext)\n const isHidden = controller?.hidden || false\n const disableDrag = disableDragProp ?? controller?.disableDrag\n const themeName = useThemeName()\n const contentRef = React.useRef<TamaguiElement>(null)\n const scrollBridge = useConstant<ScrollBridge>(() => ({\n enabled: false,\n y: 0,\n paneY: 0,\n paneMinY: 0,\n scrollStartY: -1,\n drag: () => {},\n release: () => {},\n scrollLock: false,\n }))\n\n const onOpenChangeInternal = (val: boolean) => {\n controller?.onOpenChange?.(val)\n onOpenChange?.(val)\n }\n\n const [open, setOpen] = useControllableState({\n prop: controller?.open ?? openProp,\n defaultProp: defaultOpen || true,\n onChange: onOpenChangeInternal,\n strategy: 'most-recent-wins',\n })\n\n const [frameSize, setFrameSize] = useState<number>(0)\n\n const snapPoints = useMemo(\n () => (dismissOnSnapToBottom ? [...snapPointsProp, 0] : snapPointsProp),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(snapPointsProp), dismissOnSnapToBottom]\n )\n\n // lets set -1 to be always the \"open = false\" position\n const [position_, setPosition_] = useControllableState({\n prop: positionProp,\n defaultProp: defaultPosition || (open ? 0 : -1),\n onChange: onPositionChange,\n strategy: 'most-recent-wins',\n })\n const position = open === false ? -1 : position_\n\n // reset position to fully open on re-open after dismissOnSnapToBottom\n if (open && dismissOnSnapToBottom && position === snapPoints.length - 1) {\n setPosition_(0)\n }\n\n const setPosition = useCallback(\n (next: number) => {\n // close on dismissOnSnapToBottom (and set position so it animates)\n if (dismissOnSnapToBottom && next === snapPoints.length - 1) {\n setOpen(false)\n } else {\n setPosition_(next)\n }\n },\n [dismissOnSnapToBottom, snapPoints.length, setPosition_, setOpen]\n )\n\n const animatedNumber = driver.useAnimatedNumber(HIDDEN_SIZE)\n\n // native only fix\n const at = useRef(0)\n driver.useAnimatedNumberReaction(animatedNumber, (value) => {\n at.current = value\n scrollBridge.paneY = value\n })\n\n const [isResizing, setIsResizing] = useState(true)\n useIsomorphicLayoutEffect(() => {\n if (!isResizing) {\n setIsResizing(true)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [modal])\n\n function stopSpring() {\n animatedNumber.stop()\n if (scrollBridge.onFinishAnimate) {\n scrollBridge.onFinishAnimate()\n scrollBridge.onFinishAnimate = undefined\n }\n }\n\n // open must set position\n const shouldSetPositionOpen = open && position < 0\n useEffect(() => {\n if (shouldSetPositionOpen) {\n setPosition(0)\n }\n }, [setPosition, shouldSetPositionOpen])\n\n const positions = useMemo(\n () => snapPoints.map((point) => getPercentSize(point, frameSize)),\n [frameSize, snapPoints]\n )\n\n const animateTo = useEvent((position: number) => {\n const current = animatedNumber.getValue()\n if (isHidden && open) return\n if (!current) return\n if (frameSize === 0) return\n const hiddenValue = frameSize === 0 ? HIDDEN_SIZE : frameSize\n const toValue = isHidden || position === -1 ? hiddenValue : positions[position]\n if (at.current === toValue) return\n stopSpring()\n if (isHidden || isResizing) {\n if (isResizing) {\n setIsResizing(false)\n }\n animatedNumber.setValue(toValue, {\n type: 'timing',\n duration: 0,\n })\n at.current = toValue\n return\n }\n // dont bounce on initial measure to bottom\n const overshootClamping = at.current === HIDDEN_SIZE\n animatedNumber.setValue(toValue, {\n ...animationConfig,\n type: 'spring',\n overshootClamping,\n })\n })\n\n useIsomorphicLayoutEffect(() => {\n animateTo(position)\n }, [isHidden, frameSize, position, animateTo])\n\n const panResponder = useMemo(\n () => {\n if (disableDrag) return\n if (!frameSize) return\n\n const minY = positions[0]\n scrollBridge.paneMinY = minY\n let startY = at.current\n\n function makeUnselectable(val: boolean) {\n if (!selectionStyleSheet) return\n if (!val) {\n selectionStyleSheet.innerText = ``\n } else {\n selectionStyleSheet.innerText = `:root * { user-select: none !important; -webkit-user-select: none !important; }`\n }\n }\n\n const release = ({ vy, dragAt }: { dragAt: number; vy: number }) => {\n isExternalDrag = false\n previouslyScrolling = false\n makeUnselectable(false)\n const at = dragAt + startY\n // seems liky vy goes up to about 4 at the very most (+ is down, - is up)\n // lets base our multiplier on the total layout height\n const end = at + frameSize * vy * 0.2\n let closestPoint = 0\n let dist = Infinity\n for (let i = 0; i < positions.length; i++) {\n const position = positions[i]\n const curDist = end > position ? end - position : position - end\n if (curDist < dist) {\n dist = curDist\n closestPoint = i\n }\n }\n // have to call both because state may not change but need to snap back\n setPosition(closestPoint)\n animateTo(closestPoint)\n }\n\n const finish = (_e: GestureResponderEvent, state: PanResponderGestureState) => {\n release({\n vy: state.vy,\n dragAt: state.dy,\n })\n }\n\n let previouslyScrolling = false\n\n const onMoveShouldSet = (_e: GestureResponderEvent, { dy }: PanResponderGestureState) => {\n const isScrolled = scrollBridge.y !== 0\n if (isScrolled) {\n previouslyScrolling = true\n return false\n }\n if (previouslyScrolling) {\n previouslyScrolling = false\n return true\n }\n const isDraggingUp = dy < 0\n const isAtTop = scrollBridge.paneY <= scrollBridge.paneMinY\n // prevent drag once at top and pulling up\n if (isAtTop) {\n if (!isScrolled && isDraggingUp) {\n return false\n }\n }\n // we could do some detection of other touchables and cancel here..\n return Math.abs(dy) > 8\n }\n\n const grant = () => {\n makeUnselectable(true)\n stopSpring()\n startY = at.current\n }\n\n let isExternalDrag = false\n\n scrollBridge.drag = (dy) => {\n if (!isExternalDrag) {\n isExternalDrag = true\n grant()\n }\n const to = dy + startY\n animatedNumber.setValue(resisted(to, minY), { type: 'direct' })\n }\n\n scrollBridge.release = release\n\n return PanResponder.create({\n onMoveShouldSetPanResponder: onMoveShouldSet,\n onPanResponderGrant: grant,\n onPanResponderMove: (_e, { dy }) => {\n const to = dy + startY\n animatedNumber.setValue(resisted(to, minY), { type: 'direct' })\n },\n onPanResponderEnd: finish,\n onPanResponderTerminate: finish,\n onPanResponderRelease: finish,\n })\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [disableDrag, animateTo, frameSize, positions, setPosition]\n )\n\n let handleComponent: React.ReactElement | null = null\n let overlayComponent: React.ReactElement | null = null\n let frameComponent: React.ReactElement | null = null\n\n // TODO do more radix-like and don't require direct children descendents\n React.Children.forEach(childrenProp, (child) => {\n if (isValidElement(child)) {\n const name = child.type?.['staticConfig']?.componentName\n switch (name) {\n case 'SheetHandle':\n handleComponent = child\n break\n case 'Sheet':\n frameComponent = child\n break\n case 'SheetOverlay':\n overlayComponent = child\n break\n default:\n // eslint-disable-next-line no-console\n console.warn('Warning: passed invalid child to Sheet', child)\n }\n }\n })\n\n const preventShown = controller?.hidden && controller?.open\n\n const animatedStyle = driver.useAnimatedNumberStyle(animatedNumber, (val) => {\n return {\n transform: [{ translateY: frameSize === 0 ? HIDDEN_SIZE : val }],\n }\n })\n\n if (preventShown) {\n return null\n }\n\n // temp until reanimated useAnimatedNumber fix\n const AnimatedView = driver['NumberView'] ?? driver.View\n\n const contents = (\n <SheetProvider\n modal={modal}\n contentRef={contentRef}\n dismissOnOverlayPress={dismissOnOverlayPress}\n dismissOnSnapToBottom={dismissOnSnapToBottom}\n open={open}\n hidden={isHidden}\n scope={__scopeSheet}\n position={position}\n snapPoints={snapPoints}\n setPosition={setPosition}\n setOpen={setOpen}\n scrollBridge={scrollBridge}\n >\n {isResizing ? null : overlayComponent}\n\n <AnimatedView\n ref={ref}\n {...panResponder?.panHandlers}\n onLayout={(e) => {\n const next = e.nativeEvent.layout.height\n setFrameSize((prev) => {\n const isBigChange = Math.abs(prev - next) > 50\n setIsResizing(isBigChange)\n return next\n })\n }}\n pointerEvents={open ? 'auto' : 'none'}\n style={[\n {\n position: 'absolute',\n zIndex,\n width: '100%',\n height: '100%',\n },\n animatedStyle,\n ]}\n >\n {handleComponent}\n\n <RemoveScroll\n enabled={open && modal && handleDisableScroll}\n as={Slot}\n allowPinchZoom\n shards={[contentRef]}\n // causes lots of bugs on touch web on site\n removeScrollBar={false}\n >\n {isResizing ? null : frameComponent}\n </RemoveScroll>\n </AnimatedView>\n </SheetProvider>\n )\n\n if (modal) {\n return (\n <Portal zIndex={zIndex}>\n <Theme name={themeName}>{contents}</Theme>\n </Portal>\n )\n }\n\n return contents\n })\n ),\n sheetComponents\n)\n\nexport const ControlledSheet = Sheet as FunctionComponent<\n Omit<SheetProps, 'open' | 'onOpenChange'> & RefAttributes<View>\n> &\n typeof sheetComponents\n\n/* -------------------------------------------------------------------------------------------------*/\n\nfunction getPercentSize(point?: number, frameSize?: number) {\n if (!frameSize) return 0\n if (point === undefined) {\n // eslint-disable-next-line no-console\n console.warn(`No snapPoint`)\n return 0\n }\n const pct = point / 100\n const next = Math.round(frameSize - pct * frameSize)\n return next\n}\n\nfunction resisted(y: number, minY: number, maxOverflow = 25) {\n if (y < minY) {\n const past = minY - y\n const pctPast = Math.min(maxOverflow, past) / maxOverflow\n const diminishBy = 1.1 - Math.pow(0.1, pctPast)\n const extra = -diminishBy * maxOverflow\n return minY + extra\n }\n return y\n}\n\ntype SheetControllerContextValue = {\n disableDrag?: boolean\n open?: boolean\n // hide without \"closing\" to prevent re-animation when shown again\n hidden?: boolean\n onOpenChange?: React.Dispatch<React.SetStateAction<boolean>> | ((val: boolean) => void)\n}\n\nconst SheetControllerContext = createContext<SheetControllerContextValue | null>(null)\n\nexport const SheetController = ({\n children,\n onOpenChange: onOpenChangeProp,\n ...value\n}: Partial<SheetControllerContextValue> & { children?: React.ReactNode }) => {\n const onOpenChange = useEvent(onOpenChangeProp)\n\n const memoValue = useMemo(\n () => ({\n open: value.open,\n hidden: value.hidden,\n disableDrag: value.disableDrag,\n onOpenChange,\n }),\n [onOpenChange, value.open, value.hidden, value.disableDrag]\n )\n\n return (\n <SheetControllerContext.Provider value={memoValue}>{children}</SheetControllerContext.Provider>\n )\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,uBAAuB;AAChC;AAAA,EAEE;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AACvB,SAAS,oBAAoB;AAC7B,SAAS,QAAqB,cAA2B;AACzD,SAAS,4BAA4B;AACrC,OAAO;AAAA,EAGL;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,
|
|
4
|
+
"sourcesContent": ["import { useComposedRefs } from '@tamagui/compose-refs'\nimport {\n GetProps,\n Slot,\n TamaguiElement,\n Theme,\n getAnimationDriver,\n isClient,\n isWeb,\n mergeEvent,\n styled,\n themeable,\n useConstant,\n useEvent,\n useIsomorphicLayoutEffect,\n useThemeName,\n withStaticProperties,\n} from '@tamagui/core'\nimport { Portal } from '@tamagui/portal'\nimport { RemoveScroll } from '@tamagui/remove-scroll'\nimport { XStack, XStackProps, YStack, YStackProps } from '@tamagui/stacks'\nimport { useControllableState } from '@tamagui/use-controllable-state'\nimport React, {\n FunctionComponent,\n RefAttributes,\n createContext,\n forwardRef,\n isValidElement,\n useCallback,\n useContext,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport { GestureResponderEvent, PanResponder, PanResponderGestureState, View } from 'react-native'\n\nimport { SHEET_HANDLE_NAME, SHEET_NAME } from './SHEET_HANDLE_NAME'\nimport { SheetProvider, useSheetContext } from './SheetContext'\nimport { SheetScrollView } from './SheetScrollView'\nimport { ScrollBridge, SheetProps, SheetScopedProps } from './types'\n\nexport { createSheetScope } from './SheetContext'\n\n/* -------------------------------------------------------------------------------------------------\n * SheetHandle\n * -----------------------------------------------------------------------------------------------*/\n\nexport const SheetHandleFrame = styled(XStack, {\n name: SHEET_HANDLE_NAME,\n height: 10,\n borderRadius: 100,\n backgroundColor: '$background',\n zIndex: 10,\n marginHorizontal: '35%',\n marginBottom: '$2',\n opacity: 0.5,\n\n hoverStyle: {\n opacity: 0.7,\n },\n\n variants: {\n open: {\n true: {\n pointerEvents: 'auto',\n },\n false: {\n opacity: 0,\n pointerEvents: 'none',\n },\n },\n } as const,\n})\n\nexport const SheetHandle = SheetHandleFrame.extractable(\n ({ __scopeSheet, ...props }: SheetScopedProps<XStackProps>) => {\n const context = useSheetContext(SHEET_HANDLE_NAME, __scopeSheet)\n return (\n <SheetHandleFrame\n onPress={() => {\n // don't toggle to the bottom snap position when dismissOnSnapToBottom set\n const max = context.snapPoints.length + (context.dismissOnSnapToBottom ? -1 : 0)\n const nextPos = (context.position + 1) % max\n context.setPosition(nextPos)\n }}\n open={context.open}\n {...props}\n />\n )\n }\n)\n\n/* -------------------------------------------------------------------------------------------------\n * SheetOverlay\n * -----------------------------------------------------------------------------------------------*/\n\nconst SHEET_OVERLAY_NAME = 'SheetOverlay'\n\nexport const SheetOverlayFrame = styled(YStack, {\n name: SHEET_OVERLAY_NAME,\n // TODO this should be $background without opacity and just customized by theme\n backgroundColor: '$color',\n fullscreen: true,\n opacity: 0.2,\n zIndex: 0,\n\n variants: {\n closed: {\n true: {\n opacity: 0,\n pointerEvents: 'none',\n },\n false: {\n pointerEvents: 'auto',\n },\n },\n } as const,\n})\n\nexport type SheetOverlayProps = GetProps<typeof SheetOverlayFrame>\n\nexport const SheetOverlay = SheetOverlayFrame.extractable(\n ({ __scopeSheet, ...props }: SheetScopedProps<SheetOverlayProps>) => {\n const context = useSheetContext(SHEET_OVERLAY_NAME, __scopeSheet)\n return (\n <SheetOverlayFrame\n closed={!context.open || context.hidden}\n {...props}\n onPress={mergeEvent(\n props.onPress,\n context.dismissOnOverlayPress\n ? () => {\n context.setOpen(false)\n }\n : undefined\n )}\n />\n )\n }\n)\n\n/* -------------------------------------------------------------------------------------------------\n * Sheet\n * -----------------------------------------------------------------------------------------------*/\n\nconst selectionStyleSheet = isClient ? document.createElement('style') : null\nif (selectionStyleSheet) {\n document.head.appendChild(selectionStyleSheet)\n}\n\nexport const SheetFrameFrame = styled(YStack, {\n name: SHEET_NAME,\n flex: 1,\n backgroundColor: '$background',\n borderTopLeftRadius: '$4',\n borderTopRightRadius: '$4',\n width: '100%',\n maxHeight: '100%',\n overflow: 'hidden',\n pointerEvents: 'auto',\n})\n\nexport const SheetFrame = SheetFrameFrame.extractable(\n forwardRef(({ __scopeSheet, ...props }: SheetScopedProps<YStackProps>, forwardedRef) => {\n const context = useSheetContext(SHEET_NAME, __scopeSheet)\n const composedContentRef = useComposedRefs(forwardedRef, context.contentRef)\n return <SheetFrameFrame ref={composedContentRef} {...props} />\n })\n)\n\n// set all the way off screen\nconst HIDDEN_SIZE = 10_000\n\nconst sheetComponents = {\n Handle: SheetHandle,\n Frame: SheetFrame,\n Overlay: SheetOverlay,\n ScrollView: SheetScrollView,\n}\n\nexport const Sheet = withStaticProperties(\n themeable(\n forwardRef<View, SheetProps>(function Sheet(props, ref) {\n const {\n __scopeSheet,\n snapPoints: snapPointsProp = [80],\n open: openProp,\n defaultOpen,\n children: childrenProp,\n position: positionProp,\n onPositionChange,\n onOpenChange,\n defaultPosition,\n dismissOnOverlayPress = true,\n animationConfig,\n dismissOnSnapToBottom = false,\n disableDrag: disableDragProp,\n modal = false,\n handleDisableScroll = true,\n zIndex = 40,\n } = props\n\n if (process.env.NODE_ENV === 'development') {\n if (snapPointsProp.some((p) => p < 0 || p > 100)) {\n // eslint-disable-next-line no-console\n console.warn(\n `\u26A0\uFE0F Invalid snapPoint given, snapPoints must be between 0 and 100, equal to percent height of frame`\n )\n }\n }\n\n const driver = getAnimationDriver()\n if (!driver) {\n throw new Error(`Must set animations in tamagui.config.ts`)\n }\n\n // allows for sheets to be controlled by other components\n const controller = useContext(SheetControllerContext)\n const isHidden = controller?.hidden || false\n const disableDrag = disableDragProp ?? controller?.disableDrag\n const themeName = useThemeName()\n const contentRef = React.useRef<TamaguiElement>(null)\n const scrollBridge = useConstant<ScrollBridge>(() => ({\n enabled: false,\n y: 0,\n paneY: 0,\n paneMinY: 0,\n scrollStartY: -1,\n drag: () => {},\n release: () => {},\n scrollLock: false,\n }))\n\n const onOpenChangeInternal = (val: boolean) => {\n controller?.onOpenChange?.(val)\n onOpenChange?.(val)\n }\n\n const [open, setOpen] = useControllableState({\n prop: controller?.open ?? openProp,\n defaultProp: defaultOpen || true,\n onChange: onOpenChangeInternal,\n strategy: 'most-recent-wins',\n })\n\n const [frameSize, setFrameSize] = useState<number>(0)\n\n const snapPoints = useMemo(\n () => (dismissOnSnapToBottom ? [...snapPointsProp, 0] : snapPointsProp),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(snapPointsProp), dismissOnSnapToBottom]\n )\n\n // lets set -1 to be always the \"open = false\" position\n const [position_, setPosition_] = useControllableState({\n prop: positionProp,\n defaultProp: defaultPosition || (open ? 0 : -1),\n onChange: onPositionChange,\n strategy: 'most-recent-wins',\n })\n const position = open === false ? -1 : position_\n\n // reset position to fully open on re-open after dismissOnSnapToBottom\n if (open && dismissOnSnapToBottom && position === snapPoints.length - 1) {\n setPosition_(0)\n }\n\n const setPosition = useCallback(\n (next: number) => {\n // close on dismissOnSnapToBottom (and set position so it animates)\n if (dismissOnSnapToBottom && next === snapPoints.length - 1) {\n setOpen(false)\n } else {\n setPosition_(next)\n }\n },\n [dismissOnSnapToBottom, snapPoints.length, setPosition_, setOpen]\n )\n\n const animatedNumber = driver.useAnimatedNumber(HIDDEN_SIZE)\n\n // native only fix\n const at = useRef(0)\n driver.useAnimatedNumberReaction(animatedNumber, (value) => {\n at.current = value\n scrollBridge.paneY = value\n })\n\n const [isResizing, setIsResizing] = useState(true)\n useIsomorphicLayoutEffect(() => {\n if (!isResizing) {\n setIsResizing(true)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [modal])\n\n function stopSpring() {\n animatedNumber.stop()\n if (scrollBridge.onFinishAnimate) {\n scrollBridge.onFinishAnimate()\n scrollBridge.onFinishAnimate = undefined\n }\n }\n\n // open must set position\n const shouldSetPositionOpen = open && position < 0\n useEffect(() => {\n if (shouldSetPositionOpen) {\n setPosition(0)\n }\n }, [setPosition, shouldSetPositionOpen])\n\n const positions = useMemo(\n () => snapPoints.map((point) => getPercentSize(point, frameSize)),\n [frameSize, snapPoints]\n )\n\n const animateTo = useEvent((position: number) => {\n const current = animatedNumber.getValue()\n if (isHidden && open) return\n if (!current) return\n if (frameSize === 0) return\n const hiddenValue = frameSize === 0 ? HIDDEN_SIZE : frameSize\n const toValue = isHidden || position === -1 ? hiddenValue : positions[position]\n if (at.current === toValue) return\n stopSpring()\n if (isHidden || isResizing) {\n if (isResizing) {\n setIsResizing(false)\n }\n animatedNumber.setValue(toValue, {\n type: 'timing',\n duration: 0,\n })\n at.current = toValue\n return\n }\n // dont bounce on initial measure to bottom\n const overshootClamping = at.current === HIDDEN_SIZE\n animatedNumber.setValue(toValue, {\n ...animationConfig,\n type: 'spring',\n overshootClamping,\n })\n })\n\n useIsomorphicLayoutEffect(() => {\n animateTo(position)\n }, [isHidden, frameSize, position, animateTo])\n\n const panResponder = useMemo(\n () => {\n if (disableDrag) return\n if (!frameSize) return\n\n const minY = positions[0]\n scrollBridge.paneMinY = minY\n let startY = at.current\n\n function makeUnselectable(val: boolean) {\n if (!selectionStyleSheet) return\n if (!val) {\n selectionStyleSheet.innerText = ``\n } else {\n selectionStyleSheet.innerText = `:root * { user-select: none !important; -webkit-user-select: none !important; }`\n }\n }\n\n const release = ({ vy, dragAt }: { dragAt: number; vy: number }) => {\n isExternalDrag = false\n previouslyScrolling = false\n makeUnselectable(false)\n const at = dragAt + startY\n // seems liky vy goes up to about 4 at the very most (+ is down, - is up)\n // lets base our multiplier on the total layout height\n const end = at + frameSize * vy * 0.2\n let closestPoint = 0\n let dist = Infinity\n for (let i = 0; i < positions.length; i++) {\n const position = positions[i]\n const curDist = end > position ? end - position : position - end\n if (curDist < dist) {\n dist = curDist\n closestPoint = i\n }\n }\n // have to call both because state may not change but need to snap back\n setPosition(closestPoint)\n animateTo(closestPoint)\n }\n\n const finish = (_e: GestureResponderEvent, state: PanResponderGestureState) => {\n release({\n vy: state.vy,\n dragAt: state.dy,\n })\n }\n\n let previouslyScrolling = false\n\n const onMoveShouldSet = (_e: GestureResponderEvent, { dy }: PanResponderGestureState) => {\n const isScrolled = scrollBridge.y !== 0\n if (isScrolled) {\n previouslyScrolling = true\n return false\n }\n if (previouslyScrolling) {\n previouslyScrolling = false\n return true\n }\n const isDraggingUp = dy < 0\n const isAtTop = scrollBridge.paneY <= scrollBridge.paneMinY\n // prevent drag once at top and pulling up\n if (isAtTop) {\n if (!isScrolled && isDraggingUp) {\n return false\n }\n }\n // we could do some detection of other touchables and cancel here..\n return Math.abs(dy) > 8\n }\n\n const grant = () => {\n makeUnselectable(true)\n stopSpring()\n startY = at.current\n }\n\n let isExternalDrag = false\n\n scrollBridge.drag = (dy) => {\n if (!isExternalDrag) {\n isExternalDrag = true\n grant()\n }\n const to = dy + startY\n animatedNumber.setValue(resisted(to, minY), { type: 'direct' })\n }\n\n scrollBridge.release = release\n\n return PanResponder.create({\n onMoveShouldSetPanResponder: onMoveShouldSet,\n onPanResponderGrant: grant,\n onPanResponderMove: (_e, { dy }) => {\n const toFull = dy + startY\n const to = resisted(toFull, minY)\n animatedNumber.setValue(to, { type: 'direct' })\n },\n onPanResponderEnd: finish,\n onPanResponderTerminate: finish,\n onPanResponderRelease: finish,\n })\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [disableDrag, animateTo, frameSize, positions, setPosition]\n )\n\n let handleComponent: React.ReactElement | null = null\n let overlayComponent: React.ReactElement | null = null\n let frameComponent: React.ReactElement | null = null\n\n // TODO do more radix-like and don't require direct children descendents\n React.Children.forEach(childrenProp, (child) => {\n if (isValidElement(child)) {\n const name = child.type?.['staticConfig']?.componentName\n switch (name) {\n case 'SheetHandle':\n handleComponent = child\n break\n case 'Sheet':\n frameComponent = child\n break\n case 'SheetOverlay':\n overlayComponent = child\n break\n default:\n // eslint-disable-next-line no-console\n console.warn('Warning: passed invalid child to Sheet', child)\n }\n }\n })\n\n const preventShown = controller?.hidden && controller?.open\n\n const animatedStyle = driver.useAnimatedNumberStyle(animatedNumber, (val) => {\n return {\n transform: [{ translateY: frameSize === 0 ? HIDDEN_SIZE : val }],\n }\n })\n\n if (preventShown) {\n return null\n }\n\n // temp until reanimated useAnimatedNumber fix\n const AnimatedView = driver['NumberView'] ?? driver.View\n\n /**\n * This is a hacky workaround for native:\n */\n const [isShowingInnerSheet, setIsShowingInnerSheet] = useState(false)\n const shouldHideParentSheet = !isWeb && modal && isShowingInnerSheet\n const parentSheetContext = useContext(SheetInsideSheetContext)\n const onInnerSheet = useCallback((hasChild: boolean) => {\n setIsShowingInnerSheet(hasChild)\n }, [])\n useIsomorphicLayoutEffect(() => {\n if (!parentSheetContext || !open) return\n parentSheetContext(true)\n return () => {\n parentSheetContext(false)\n }\n }, [parentSheetContext, open])\n\n const contents = (\n <SheetProvider\n modal={modal}\n contentRef={contentRef}\n dismissOnOverlayPress={dismissOnOverlayPress}\n dismissOnSnapToBottom={dismissOnSnapToBottom}\n open={open}\n hidden={isHidden}\n scope={__scopeSheet}\n position={position}\n snapPoints={snapPoints}\n setPosition={setPosition}\n setOpen={setOpen}\n scrollBridge={scrollBridge}\n >\n {isResizing || shouldHideParentSheet ? null : overlayComponent}\n\n <AnimatedView\n ref={ref}\n {...panResponder?.panHandlers}\n onLayout={(e) => {\n const next = e.nativeEvent.layout.height\n setFrameSize((prev) => {\n const isBigChange = Math.abs(prev - next) > 50\n setIsResizing(isBigChange)\n return next\n })\n }}\n pointerEvents={open && !shouldHideParentSheet ? 'auto' : 'none'}\n style={[\n {\n position: 'absolute',\n zIndex,\n width: '100%',\n height: '100%',\n opacity: shouldHideParentSheet ? 0 : 1,\n },\n animatedStyle,\n ]}\n >\n {handleComponent}\n\n <RemoveScroll\n enabled={open && modal && handleDisableScroll}\n as={Slot}\n allowPinchZoom\n shards={[contentRef]}\n // causes lots of bugs on touch web on site\n removeScrollBar={false}\n >\n {isResizing ? null : frameComponent}\n </RemoveScroll>\n </AnimatedView>\n </SheetProvider>\n )\n\n if (modal) {\n const modalContents = (\n <Portal zIndex={zIndex}>\n <Theme name={themeName}>{contents}</Theme>\n </Portal>\n )\n\n if (isWeb) {\n return modalContents\n }\n\n // on native we don't support multiple modals yet... fix for now is to hide outer one\n return (\n <SheetInsideSheetContext.Provider value={onInnerSheet}>\n {modalContents}\n </SheetInsideSheetContext.Provider>\n )\n }\n\n return contents\n })\n ),\n sheetComponents\n)\n\nconst SheetInsideSheetContext = createContext<((hasChild: boolean) => void) | null>(null)\n\nexport const ControlledSheet = Sheet as FunctionComponent<\n Omit<SheetProps, 'open' | 'onOpenChange'> & RefAttributes<View>\n> &\n typeof sheetComponents\n\n/* -------------------------------------------------------------------------------------------------*/\n\nfunction getPercentSize(point?: number, frameSize?: number) {\n if (!frameSize) return 0\n if (point === undefined) {\n // eslint-disable-next-line no-console\n console.warn(`No snapPoint`)\n return 0\n }\n const pct = point / 100\n const next = Math.round(frameSize - pct * frameSize)\n return next\n}\n\nfunction resisted(y: number, minY: number, maxOverflow = 25) {\n if (y < minY) {\n const past = minY - y\n const pctPast = Math.min(maxOverflow, past) / maxOverflow\n const diminishBy = 1.1 - Math.pow(0.1, pctPast)\n const extra = -diminishBy * maxOverflow\n return minY + extra\n }\n return y\n}\n\ntype SheetControllerContextValue = {\n disableDrag?: boolean\n open?: boolean\n // hide without \"closing\" to prevent re-animation when shown again\n hidden?: boolean\n onOpenChange?: React.Dispatch<React.SetStateAction<boolean>> | ((val: boolean) => void)\n}\n\nconst SheetControllerContext = createContext<SheetControllerContextValue | null>(null)\n\nexport const SheetController = ({\n children,\n onOpenChange: onOpenChangeProp,\n ...value\n}: Partial<SheetControllerContextValue> & { children?: React.ReactNode }) => {\n const onOpenChange = useEvent(onOpenChangeProp)\n\n const memoValue = useMemo(\n () => ({\n open: value.open,\n hidden: value.hidden,\n disableDrag: value.disableDrag,\n onOpenChange,\n }),\n [onOpenChange, value.open, value.hidden, value.disableDrag]\n )\n\n return (\n <SheetControllerContext.Provider value={memoValue}>{children}</SheetControllerContext.Provider>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["Sheet", "position", "at"]
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/SheetScrollView.tsx"],
|
|
4
|
-
"sourcesContent": ["import { TamaguiElement } from '@tamagui/core'\nimport { ScrollView, ScrollViewProps } from '@tamagui/scroll-view'\nimport { forwardRef, useRef, useState } from 'react'\n\nimport { useSheetContext } from './SheetContext'\nimport { SheetScopedProps } from './types'\n\n/* -------------------------------------------------------------------------------------------------\n * SheetScrollView\n * -----------------------------------------------------------------------------------------------*/\n\nconst SHEET_SCROLL_VIEW_NAME = 'SheetScrollView'\n\nexport const SheetScrollView = forwardRef<TamaguiElement, ScrollViewProps>(\n ({ __scopeSheet, ...props }: SheetScopedProps<ScrollViewProps>, ref) => {\n const { scrollBridge } = useSheetContext(SHEET_SCROLL_VIEW_NAME, __scopeSheet)\n const [scrollEnabled, setScrollEnabled] = useState(true)\n const state = useRef({\n lastPageY: 0,\n dragAt: 0,\n dys: [] as number[], // store a few recent dys to get velocity on release\n isScrolling: false,\n })\n\n const release = () => {\n scrollBridge.scrollStartY = -1\n state.current.isScrolling = false\n setScrollEnabled(true)\n let vy = 0\n if (state.current.dys.length) {\n const recentDys = state.current.dys.slice(-10)\n const dist = recentDys.length ? recentDys.reduce((a, b) => a + b, 0) : 0\n const avgDy = dist / recentDys.length\n vy = avgDy * 0.04\n }\n state.current.dys = []\n scrollBridge.release({\n dragAt: state.current.dragAt,\n vy,\n })\n }\n\n return (\n <ScrollView\n ref={ref}\n flex={1}\n scrollEventThrottle={8}\n scrollEnabled={scrollEnabled}\n onScroll={(e) => {\n const { y } = e.nativeEvent.contentOffset\n scrollBridge.y = y\n if (y > 0) {\n scrollBridge.scrollStartY = -1\n }\n }}\n onStartShouldSetResponder={() => {\n scrollBridge.scrollStartY = -1\n return true\n }}\n onMoveShouldSetResponder={() => true}\n onResponderMove={(e) => {\n const { pageY } = e.nativeEvent\n\n if (state.current.isScrolling) {\n return\n }\n\n if (scrollBridge.scrollStartY === -1) {\n scrollBridge.scrollStartY = pageY\n state.current.lastPageY = pageY\n }\n\n const dragAt = pageY - scrollBridge.scrollStartY\n const dy = pageY - state.current.lastPageY\n state.current.lastPageY = pageY // after dy\n
|
|
5
|
-
"mappings": "AACA,SAAS,kBAAmC;AAC5C,SAAS,YAAY,QAAQ,gBAAgB;AAE7C,SAAS,uBAAuB;
|
|
4
|
+
"sourcesContent": ["import { TamaguiElement } from '@tamagui/core'\nimport { ScrollView, ScrollViewProps } from '@tamagui/scroll-view'\nimport { forwardRef, useRef, useState } from 'react'\n\nimport { useSheetContext } from './SheetContext'\nimport { SheetScopedProps } from './types'\n\n// TODO ideally would replicate https://github.com/ammarahm-ed/react-native-actions-sheet/blob/master/src/index.tsx\n\n/* -------------------------------------------------------------------------------------------------\n * SheetScrollView\n * -----------------------------------------------------------------------------------------------*/\n\nconst SHEET_SCROLL_VIEW_NAME = 'SheetScrollView'\n\nexport const SheetScrollView = forwardRef<TamaguiElement, ScrollViewProps>(\n ({ __scopeSheet, ...props }: SheetScopedProps<ScrollViewProps>, ref) => {\n const { scrollBridge } = useSheetContext(SHEET_SCROLL_VIEW_NAME, __scopeSheet)\n const [scrollEnabled, setScrollEnabled] = useState(true)\n const state = useRef({\n lastPageY: 0,\n dragAt: 0,\n dys: [] as number[], // store a few recent dys to get velocity on release\n isScrolling: false,\n })\n\n const release = () => {\n scrollBridge.scrollStartY = -1\n state.current.isScrolling = false\n setScrollEnabled(true)\n let vy = 0\n if (state.current.dys.length) {\n const recentDys = state.current.dys.slice(-10)\n const dist = recentDys.length ? recentDys.reduce((a, b) => a + b, 0) : 0\n const avgDy = dist / recentDys.length\n vy = avgDy * 0.04\n }\n state.current.dys = []\n scrollBridge.release({\n dragAt: state.current.dragAt,\n vy,\n })\n }\n\n return (\n <ScrollView\n ref={ref}\n flex={1}\n scrollEventThrottle={8}\n scrollEnabled={scrollEnabled}\n onScroll={(e) => {\n const { y } = e.nativeEvent.contentOffset\n scrollBridge.y = y\n if (y > 0) {\n scrollBridge.scrollStartY = -1\n }\n }}\n onStartShouldSetResponder={() => {\n scrollBridge.scrollStartY = -1\n return true\n }}\n onMoveShouldSetResponder={() => true}\n onResponderMove={(e) => {\n const { pageY } = e.nativeEvent\n\n if (state.current.isScrolling) {\n return\n }\n\n if (scrollBridge.scrollStartY === -1) {\n scrollBridge.scrollStartY = pageY\n state.current.lastPageY = pageY\n }\n\n const dragAt = pageY - scrollBridge.scrollStartY\n const dy = pageY - state.current.lastPageY\n state.current.lastPageY = pageY // after dy\n const isDraggingUp = dy < 0\n const isPaneAtTop = scrollBridge.paneY <= scrollBridge.paneMinY\n\n if ((dy === 0 || isDraggingUp) && isPaneAtTop) {\n state.current.isScrolling = true\n setScrollEnabled(true)\n return\n }\n\n setScrollEnabled(false)\n scrollBridge.drag(dragAt)\n state.current.dragAt = dragAt\n state.current.dys.push(dy)\n // only do every so often, cut down to 10 again\n if (state.current.dys.length > 100) {\n state.current.dys = state.current.dys.slice(-10)\n }\n }}\n onResponderRelease={release}\n {...props}\n />\n )\n }\n)\n"],
|
|
5
|
+
"mappings": "AACA,SAAS,kBAAmC;AAC5C,SAAS,YAAY,QAAQ,gBAAgB;AAE7C,SAAS,uBAAuB;AAShC,MAAM,yBAAyB;AAExB,MAAM,kBAAkB;AAAA,EAC7B,CAAC,EAAE,iBAAiB,MAAM,GAAsC,QAAQ;AACtE,UAAM,EAAE,aAAa,IAAI,gBAAgB,wBAAwB,YAAY;AAC7E,UAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,IAAI;AACvD,UAAM,QAAQ,OAAO;AAAA,MACnB,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,KAAK,CAAC;AAAA,MACN,aAAa;AAAA,IACf,CAAC;AAED,UAAM,UAAU,MAAM;AACpB,mBAAa,eAAe;AAC5B,YAAM,QAAQ,cAAc;AAC5B,uBAAiB,IAAI;AACrB,UAAI,KAAK;AACT,UAAI,MAAM,QAAQ,IAAI,QAAQ;AAC5B,cAAM,YAAY,MAAM,QAAQ,IAAI,MAAM,GAAG;AAC7C,cAAM,OAAO,UAAU,SAAS,UAAU,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI;AACvE,cAAM,QAAQ,OAAO,UAAU;AAC/B,aAAK,QAAQ;AAAA,MACf;AACA,YAAM,QAAQ,MAAM,CAAC;AACrB,mBAAa,QAAQ;AAAA,QACnB,QAAQ,MAAM,QAAQ;AAAA,QACtB;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WACE,CAAC,WACC,KAAK,KACL,MAAM,GACN,qBAAqB,GACrB,eAAe,eACf,UAAU,CAAC,MAAM;AACf,YAAM,EAAE,EAAE,IAAI,EAAE,YAAY;AAC5B,mBAAa,IAAI;AACjB,UAAI,IAAI,GAAG;AACT,qBAAa,eAAe;AAAA,MAC9B;AAAA,IACF,GACA,2BAA2B,MAAM;AAC/B,mBAAa,eAAe;AAC5B,aAAO;AAAA,IACT,GACA,0BAA0B,MAAM,MAChC,iBAAiB,CAAC,MAAM;AACtB,YAAM,EAAE,MAAM,IAAI,EAAE;AAEpB,UAAI,MAAM,QAAQ,aAAa;AAC7B;AAAA,MACF;AAEA,UAAI,aAAa,iBAAiB,IAAI;AACpC,qBAAa,eAAe;AAC5B,cAAM,QAAQ,YAAY;AAAA,MAC5B;AAEA,YAAM,SAAS,QAAQ,aAAa;AACpC,YAAM,KAAK,QAAQ,MAAM,QAAQ;AACjC,YAAM,QAAQ,YAAY;AAC1B,YAAM,eAAe,KAAK;AAC1B,YAAM,cAAc,aAAa,SAAS,aAAa;AAEvD,WAAK,OAAO,KAAK,iBAAiB,aAAa;AAC7C,cAAM,QAAQ,cAAc;AAC5B,yBAAiB,IAAI;AACrB;AAAA,MACF;AAEA,uBAAiB,KAAK;AACtB,mBAAa,KAAK,MAAM;AACxB,YAAM,QAAQ,SAAS;AACvB,YAAM,QAAQ,IAAI,KAAK,EAAE;AAEzB,UAAI,MAAM,QAAQ,IAAI,SAAS,KAAK;AAClC,cAAM,QAAQ,MAAM,MAAM,QAAQ,IAAI,MAAM,GAAG;AAAA,MACjD;AAAA,IACF,GACA,oBAAoB,aAChB,OACN;AAAA,EAEJ;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tamagui/sheet",
|
|
3
|
-
"version": "1.0.1-beta.
|
|
3
|
+
"version": "1.0.1-beta.176",
|
|
4
4
|
"sideEffects": [
|
|
5
5
|
"*.css"
|
|
6
6
|
],
|
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
"lint:fix": "yarn lint --fix"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@tamagui/animations-react-native": "^1.0.1-beta.
|
|
26
|
-
"@tamagui/compose-refs": "^1.0.1-beta.
|
|
27
|
-
"@tamagui/core": "^1.0.1-beta.
|
|
28
|
-
"@tamagui/create-context": "^1.0.1-beta.
|
|
29
|
-
"@tamagui/remove-scroll": "^1.0.1-beta.
|
|
30
|
-
"@tamagui/scroll-view": "^1.0.1-beta.
|
|
31
|
-
"@tamagui/stacks": "^1.0.1-beta.
|
|
32
|
-
"@tamagui/use-controllable-state": "^1.0.1-beta.
|
|
25
|
+
"@tamagui/animations-react-native": "^1.0.1-beta.176",
|
|
26
|
+
"@tamagui/compose-refs": "^1.0.1-beta.176",
|
|
27
|
+
"@tamagui/core": "^1.0.1-beta.176",
|
|
28
|
+
"@tamagui/create-context": "^1.0.1-beta.176",
|
|
29
|
+
"@tamagui/remove-scroll": "^1.0.1-beta.176",
|
|
30
|
+
"@tamagui/scroll-view": "^1.0.1-beta.176",
|
|
31
|
+
"@tamagui/stacks": "^1.0.1-beta.176",
|
|
32
|
+
"@tamagui/use-controllable-state": "^1.0.1-beta.176"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"react": "*",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"react-native": "*"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@tamagui/build": "^1.0.1-beta.
|
|
40
|
+
"@tamagui/build": "^1.0.1-beta.176",
|
|
41
41
|
"react": "*",
|
|
42
42
|
"react-dom": "*",
|
|
43
43
|
"react-native": "*"
|
package/src/Sheet.tsx
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
Theme,
|
|
7
7
|
getAnimationDriver,
|
|
8
8
|
isClient,
|
|
9
|
+
isWeb,
|
|
9
10
|
mergeEvent,
|
|
10
11
|
styled,
|
|
11
12
|
themeable,
|
|
@@ -28,6 +29,7 @@ import React, {
|
|
|
28
29
|
useCallback,
|
|
29
30
|
useContext,
|
|
30
31
|
useEffect,
|
|
32
|
+
useId,
|
|
31
33
|
useMemo,
|
|
32
34
|
useRef,
|
|
33
35
|
useState,
|
|
@@ -443,8 +445,9 @@ export const Sheet = withStaticProperties(
|
|
|
443
445
|
onMoveShouldSetPanResponder: onMoveShouldSet,
|
|
444
446
|
onPanResponderGrant: grant,
|
|
445
447
|
onPanResponderMove: (_e, { dy }) => {
|
|
446
|
-
const
|
|
447
|
-
|
|
448
|
+
const toFull = dy + startY
|
|
449
|
+
const to = resisted(toFull, minY)
|
|
450
|
+
animatedNumber.setValue(to, { type: 'direct' })
|
|
448
451
|
},
|
|
449
452
|
onPanResponderEnd: finish,
|
|
450
453
|
onPanResponderTerminate: finish,
|
|
@@ -495,6 +498,23 @@ export const Sheet = withStaticProperties(
|
|
|
495
498
|
// temp until reanimated useAnimatedNumber fix
|
|
496
499
|
const AnimatedView = driver['NumberView'] ?? driver.View
|
|
497
500
|
|
|
501
|
+
/**
|
|
502
|
+
* This is a hacky workaround for native:
|
|
503
|
+
*/
|
|
504
|
+
const [isShowingInnerSheet, setIsShowingInnerSheet] = useState(false)
|
|
505
|
+
const shouldHideParentSheet = !isWeb && modal && isShowingInnerSheet
|
|
506
|
+
const parentSheetContext = useContext(SheetInsideSheetContext)
|
|
507
|
+
const onInnerSheet = useCallback((hasChild: boolean) => {
|
|
508
|
+
setIsShowingInnerSheet(hasChild)
|
|
509
|
+
}, [])
|
|
510
|
+
useIsomorphicLayoutEffect(() => {
|
|
511
|
+
if (!parentSheetContext || !open) return
|
|
512
|
+
parentSheetContext(true)
|
|
513
|
+
return () => {
|
|
514
|
+
parentSheetContext(false)
|
|
515
|
+
}
|
|
516
|
+
}, [parentSheetContext, open])
|
|
517
|
+
|
|
498
518
|
const contents = (
|
|
499
519
|
<SheetProvider
|
|
500
520
|
modal={modal}
|
|
@@ -510,7 +530,7 @@ export const Sheet = withStaticProperties(
|
|
|
510
530
|
setOpen={setOpen}
|
|
511
531
|
scrollBridge={scrollBridge}
|
|
512
532
|
>
|
|
513
|
-
{isResizing ? null : overlayComponent}
|
|
533
|
+
{isResizing || shouldHideParentSheet ? null : overlayComponent}
|
|
514
534
|
|
|
515
535
|
<AnimatedView
|
|
516
536
|
ref={ref}
|
|
@@ -523,13 +543,14 @@ export const Sheet = withStaticProperties(
|
|
|
523
543
|
return next
|
|
524
544
|
})
|
|
525
545
|
}}
|
|
526
|
-
pointerEvents={open ? 'auto' : 'none'}
|
|
546
|
+
pointerEvents={open && !shouldHideParentSheet ? 'auto' : 'none'}
|
|
527
547
|
style={[
|
|
528
548
|
{
|
|
529
549
|
position: 'absolute',
|
|
530
550
|
zIndex,
|
|
531
551
|
width: '100%',
|
|
532
552
|
height: '100%',
|
|
553
|
+
opacity: shouldHideParentSheet ? 0 : 1,
|
|
533
554
|
},
|
|
534
555
|
animatedStyle,
|
|
535
556
|
]}
|
|
@@ -551,11 +572,22 @@ export const Sheet = withStaticProperties(
|
|
|
551
572
|
)
|
|
552
573
|
|
|
553
574
|
if (modal) {
|
|
554
|
-
|
|
575
|
+
const modalContents = (
|
|
555
576
|
<Portal zIndex={zIndex}>
|
|
556
577
|
<Theme name={themeName}>{contents}</Theme>
|
|
557
578
|
</Portal>
|
|
558
579
|
)
|
|
580
|
+
|
|
581
|
+
if (isWeb) {
|
|
582
|
+
return modalContents
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// on native we don't support multiple modals yet... fix for now is to hide outer one
|
|
586
|
+
return (
|
|
587
|
+
<SheetInsideSheetContext.Provider value={onInnerSheet}>
|
|
588
|
+
{modalContents}
|
|
589
|
+
</SheetInsideSheetContext.Provider>
|
|
590
|
+
)
|
|
559
591
|
}
|
|
560
592
|
|
|
561
593
|
return contents
|
|
@@ -564,6 +596,8 @@ export const Sheet = withStaticProperties(
|
|
|
564
596
|
sheetComponents
|
|
565
597
|
)
|
|
566
598
|
|
|
599
|
+
const SheetInsideSheetContext = createContext<((hasChild: boolean) => void) | null>(null)
|
|
600
|
+
|
|
567
601
|
export const ControlledSheet = Sheet as FunctionComponent<
|
|
568
602
|
Omit<SheetProps, 'open' | 'onOpenChange'> & RefAttributes<View>
|
|
569
603
|
> &
|
package/src/SheetScrollView.tsx
CHANGED
|
@@ -5,6 +5,8 @@ import { forwardRef, useRef, useState } from 'react'
|
|
|
5
5
|
import { useSheetContext } from './SheetContext'
|
|
6
6
|
import { SheetScopedProps } from './types'
|
|
7
7
|
|
|
8
|
+
// TODO ideally would replicate https://github.com/ammarahm-ed/react-native-actions-sheet/blob/master/src/index.tsx
|
|
9
|
+
|
|
8
10
|
/* -------------------------------------------------------------------------------------------------
|
|
9
11
|
* SheetScrollView
|
|
10
12
|
* -----------------------------------------------------------------------------------------------*/
|
|
@@ -73,9 +75,6 @@ export const SheetScrollView = forwardRef<TamaguiElement, ScrollViewProps>(
|
|
|
73
75
|
const dragAt = pageY - scrollBridge.scrollStartY
|
|
74
76
|
const dy = pageY - state.current.lastPageY
|
|
75
77
|
state.current.lastPageY = pageY // after dy
|
|
76
|
-
// const isAboveStart = dragAt <= 0
|
|
77
|
-
// const isDraggingDown = dy > 0
|
|
78
|
-
// const isScrollAtTop = scrollBridge.y <= 0
|
|
79
78
|
const isDraggingUp = dy < 0
|
|
80
79
|
const isPaneAtTop = scrollBridge.paneY <= scrollBridge.paneMinY
|
|
81
80
|
|
|
@@ -95,8 +94,6 @@ export const SheetScrollView = forwardRef<TamaguiElement, ScrollViewProps>(
|
|
|
95
94
|
}
|
|
96
95
|
}}
|
|
97
96
|
onResponderRelease={release}
|
|
98
|
-
// onResponderEnd={release}
|
|
99
|
-
// onResponderTerminate={release}
|
|
100
97
|
{...props}
|
|
101
98
|
/>
|
|
102
99
|
)
|