@webority/mobile-ui 0.2.1 → 0.3.0

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.
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.useBottomSheet=exports.default=exports.BottomSheet=void 0;var _react=_interopRequireWildcard(require("react")),_reactNative=require("react-native"),_reactNativeGestureHandler=require("react-native-gesture-handler"),_reactNativeKeyboardController=require("react-native-keyboard-controller"),_reactNativeReanimated=_interopRequireWildcard(require("react-native-reanimated")),_reactNativeSafeAreaContext=require("react-native-safe-area-context"),_index=require("../../theme/index.js"),_index2=require("../../utils/index.js"),_corners=require("../../utils/corners.js"),_ToastProvider=require("../Toast/ToastProvider.js"),_jsxRuntime=require("react/jsx-runtime");function _interopRequireWildcard(e,t){if("function"==typeof WeakMap)var a=new WeakMap,r=new WeakMap;return(_interopRequireWildcard=function(e,t){if(!t&&e&&e.__esModule)return e;var o,n,i={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return i;if(o=t?r:a){if(o.has(e))return o.get(e);o.set(e,i)}for(const t in e)"default"!==t&&{}.hasOwnProperty.call(e,t)&&((n=(o=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,t))&&(n.get||n.set)?o(i,t,n):i[t]=e[t]);return i})(e,t)}const TABLET_MIN_SHORT_SIDE=600,DIALOG_MAX_WIDTH=560,BottomSheetContext=(0,_react.createContext)(null),useBottomSheet=()=>{const e=(0,_react.useContext)(BottomSheetContext);if(!e)throw new Error("useBottomSheet must be used inside a <BottomSheet>.");return e};exports.useBottomSheet=useBottomSheet;const SPRING_CONFIG={damping:20,stiffness:240,mass:1},CLOSE_VELOCITY_THRESHOLD=1e3,DRAG_ACTIVATION_OFFSET=10,BottomSheet=exports.BottomSheet=(0,_react.forwardRef)((e,t)=>{const{snapPoints:a,index:r,onChange:o,onAnimate:n,onAfterClose:i,enablePanDownToClose:s=!0,enableBackdropPress:l=!0,scrollable:c=!1,scrollRef:u,onScroll:d,onContentSizeChange:_,onScrollLayout:m,scrollEventThrottle:h,keyboardBehavior:v="shift",mode:f="modal",presentation:b="sheet",handleIndicatorStyle:p,containerStyle:S,header:g,footer:x,headerStyle:R,footerStyle:y,children:N,accessibilityLabel:w,accessibilityViewIsModal:j,testID:C}=e,k=(0,_index.useTheme)(),I=(0,_reactNativeSafeAreaContext.useSafeAreaInsets)(),[M,O]=(0,_react.useState)(()=>_reactNative.Dimensions.get("window").height),[T,H]=(0,_react.useState)(()=>_reactNative.Dimensions.get("window").width),B=(0,_react.useCallback)(e=>{const{height:t,width:a}=e.nativeEvent.layout;t>0&&O(e=>e===t?e:t),a>0&&H(e=>e===a?e:a)},[]),P=(0,_reactNative.useWindowDimensions)(),G="dialog"===b||"auto"===b&&Math.min(P.width,P.height)>=600,D=Math.min(560,T-2*k.spacing.xl),[V,A]=(0,_react.useState)({top:I.top,bottom:I.bottom}),E="modal"===f?V.top:I.top,L="modal"===f?V.bottom:I.bottom,q=a.includes("content"),[W,F]=useMeasuredHeight(),[J,z]=useMeasuredHeight(),[Y,$,K]=useMeasuredHeight(),[X,U]=useMeasuredHeight(),Q=G?k.spacing.md:W,Z=q?Math.min(Q+(null!=g?J:0)+Y+(null!=x?X:0)+L,M-E):0,ee=(0,_react.useCallback)((e,t)=>{q&&K(t),_?.(e,t)},[q,_,K]),te=(0,_react.useMemo)(()=>resolveSnapPoints(a,M,Z),[a,M,Z]),ae=M,re=te[te.length-1]??0,oe=(0,_reactNativeReanimated.useSharedValue)(ae),ne=(0,_reactNativeReanimated.useSharedValue)(ae),ie=(0,_reactNativeReanimated.useSharedValue)(-1),[se,le]=(0,_react.useState)(-1),ce=(0,_react.useRef)(!1),[ue,de]=(0,_react.useState)(!1),[_e,me]=(0,_react.useState)(!1),he=(0,_react.useRef)(!1),ve=(0,_react.useRef)(i);ve.current=i;const[fe,be]=(0,_react.useState)(!1),pe=(0,_react.useCallback)(e=>{if(e<0||e>=te.length)return ae;const t=te[e];return G?(M-t)/2:M-t},[te,M,ae,G]),Se=(0,_react.useCallback)(e=>{se!==e&&(le(e),ie.value=e,o?.(e))},[se,ie,o]),ge=(0,_react.useCallback)(()=>{ce.current=!1,ie.value<0&&(he.current=!0,"modal"===f?(de(!1),"ios"!==_reactNative.Platform.OS&&me(!1)):be(!1))},[f,ie]),xe=(0,_react.useCallback)(()=>{he.current&&me(!1)},[]);(0,_react.useEffect)(()=>{("modal"===f?!_e:!fe)&&he.current&&(he.current=!1,ve.current?.())},[f,_e,fe]);const Re=(0,_react.useCallback)((e,t,a)=>{ce.current=!0,n?.(t,a),oe.value=(0,_reactNativeReanimated.withSpring)(e,SPRING_CONFIG,e=>{"worklet";e&&(0,_reactNativeReanimated.runOnJS)(ge)()})},[n,oe,ge]),ye=(0,_react.useCallback)(e=>{const t="number"==typeof e?clamp(e,0,te.length-1):se>=0?se:0,a=ie.value,r=pe(t);he.current=!1,"modal"===f?(me(!0),de(!0)):be(!0),a<0&&(oe.value=ae),Se(t),Re(r,a,t)},[Re,ae,se,ie,f,te.length,Se,oe,pe]),Ne=(0,_react.useCallback)(()=>{if(0===te.length)return;const e=ie.value,t=pe(0);Se(0),Re(t,e,0)},[Re,ie,te.length,Se,pe]),we=(0,_react.useCallback)(()=>{const e=ie.value;Se(-1),ce.current=!0,n?.(e,-1),oe.value=(0,_reactNativeReanimated.withTiming)(ae,{duration:k.motion.duration.fast,easing:_reactNativeReanimated.Easing.bezier(...k.motion.easing.accelerate)},e=>{"worklet";e&&(0,_reactNativeReanimated.runOnJS)(ge)()})},[ae,ie,ge,n,Se,oe,k.motion.duration.fast,k.motion.easing.accelerate]);(0,_react.useImperativeHandle)(t,()=>({expand:ye,collapse:Ne,close:we}),[ye,Ne,we]),(0,_react.useEffect)(()=>{"number"==typeof r&&r!==se&&(-1===r?we():ye(r))},[r]);const je=(0,_react.useRef)({hostHeight:M,contentSnap:Z});(0,_react.useEffect)(()=>{const e=je.current;e.hostHeight===M&&e.contentSnap===Z||(je.current={hostHeight:M,contentSnap:Z},e.hostHeight===M&&ie.value<0||(oe.value=(0,_reactNativeReanimated.withSpring)(pe(ie.value),SPRING_CONFIG)))},[M,Z]);const Ce=M-re,ke=(0,_react.useMemo)(()=>te.map(e=>M-e),[te,M]),Ie=(0,_react.useCallback)((e,t)=>{const a=ie.value;if(-1===e)return(0,_index2.triggerHaptic)("selection"),Se(-1),ce.current=!0,n?.(a,-1),void(oe.value=(0,_reactNativeReanimated.withTiming)(ae,{duration:k.motion.duration.fast,easing:_reactNativeReanimated.Easing.bezier(...k.motion.easing.accelerate)},e=>{"worklet";e&&(0,_reactNativeReanimated.runOnJS)(ge)()}));Se(e),Re(t,a,e)},[Re,ae,ie,ge,n,Se,oe,k.motion.duration.fast,k.motion.easing.accelerate]),Me=(0,_react.useMemo)(()=>_reactNativeGestureHandler.Gesture.Native().withTestId(C?`${C}-content-gesture`:"bottom-sheet-content-gesture"),[C]),Oe=(0,_react.useMemo)(()=>{const e=ke,t=ae,a=Ce,r=s;return _reactNativeGestureHandler.Gesture.Pan().withTestId(C?`${C}-pan-gesture`:"bottom-sheet-pan-gesture").activeOffsetY([-10,10]).failOffsetX([-15,15]).onStart(()=>{"worklet";ne.value=oe.value}).onUpdate(e=>{"worklet";const t=ne.value+e.translationY;oe.value=t<a?a+.25*(t-a):t}).onEnd(a=>{"worklet";const o=oe.value;if(a.velocityY>1e3)return r?void(0,_reactNativeReanimated.runOnJS)(Ie)(-1,t):void(0,_reactNativeReanimated.runOnJS)(Ie)(0,e[0]);let n=0,i=Math.abs(o-e[0]);for(let t=1;t<e.length;t++){const a=Math.abs(o-e[t]);a<i&&(i=a,n=t)}const s=e[0];r&&o-s>80?(0,_reactNativeReanimated.runOnJS)(Ie)(-1,t):(0,_reactNativeReanimated.runOnJS)(Ie)(n,e[n])})},[ae,ne,s,Ie,Ce,ke,C,oe]),{height:Te}=(0,_reactNativeKeyboardController.useReanimatedKeyboardAnimation)(),He="shift"===v,Be=(0,_reactNativeReanimated.useDerivedValue)(()=>He?Te.value:0),Pe=te[se>=0?se:0]??re,Ge=k.spacing.md,De=(0,_reactNativeReanimated.useAnimatedStyle)(()=>{if(G){const e=Be.value,t=M+e-Pe-Ge,a=e<0&&oe.value>t?t:oe.value;return{top:a<E?E:a}}const e=oe.value+Be.value,t=Be.value<0?E:Ce;return{top:e<t?t:e}}),Ve=(0,_reactNativeReanimated.useAnimatedStyle)(()=>{const e=Be.value;if(G){const t=M+e-Pe-Ge,a=e<0&&oe.value>t?t:oe.value,r=M+e-Ge-(a<E?E:a);return{height:r<0?0:r>Pe?Pe:r}}const t=e<0?E:Ce,a=oe.value+e,r=M+e-(a<t?t:a);return{height:r<0?0:r>re?re:r}}),Ae=se>=0,Ee=(0,_react.useMemo)(()=>buildStyles(k),[k]),Le=(0,_react.useCallback)(()=>{l&&((0,_index2.triggerHaptic)("selection"),we())},[l,we]),qe=(0,_react.useMemo)(()=>_reactNativeGestureHandler.Gesture.Tap().withTestId(C?`${C}-backdrop-gesture`:"bottom-sheet-backdrop-gesture").maxDuration(250).onEnd((e,t)=>{"worklet";t&&(0,_reactNativeReanimated.runOnJS)(Le)()}),[Le,C]),We=(0,_react.useMemo)(()=>({snapIndex:se,snapPoints:te,expand:ye,collapse:Ne,close:we}),[se,te,ye,Ne,we]);if("inline"===f&&!fe)return null;if("modal"===f&&!_e)return null;const Fe=(0,_jsxRuntime.jsxs)(_reactNative.View,{collapsable:!1,style:["modal"===f?Ee.backdropModal:Ee.backdropInline,{backgroundColor:k.colors.background.overlay}],onLayout:B,testID:C,accessibilityViewIsModal:j??Ae,children:[(0,_jsxRuntime.jsx)(_reactNativeGestureHandler.GestureDetector,{gesture:qe,children:(0,_jsxRuntime.jsx)(_reactNativeReanimated.default.View,{style:_reactNative.StyleSheet.absoluteFill,accessibilityRole:"button",accessibilityLabel:"Close bottom sheet"})}),(0,_jsxRuntime.jsx)(_reactNativeReanimated.default.View,{accessibilityRole:"alert",accessibilityLabel:w,accessibilityViewIsModal:j??Ae,style:[Ee.sheet,{height:re,backgroundColor:k.colors.background.elevated,borderTopLeftRadius:k.radius["2xl"],borderTopRightRadius:k.radius["2xl"],..._corners.smoothCorners,...k.shadows.xl},G?{height:Pe,left:(T-D)/2,right:void 0,width:D,borderBottomLeftRadius:k.radius["2xl"],borderBottomRightRadius:k.radius["2xl"]}:null,S,De],children:(0,_jsxRuntime.jsxs)(SheetBody,{style:[Ee.body,Ve],keyboardOffset:Be,children:[G?(0,_jsxRuntime.jsx)(_reactNative.View,{style:{height:k.spacing.md}}):(0,_jsxRuntime.jsx)(_reactNativeGestureHandler.GestureDetector,{gesture:Oe,children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:Ee.handleRow,onLayout:q?F:void 0,accessible:!0,accessibilityLabel:"Drag handle",accessibilityHint:"Drag up or down to resize the sheet, or swipe down to close it",testID:C?`${C}-handle`:"bottom-sheet-handle",children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:[Ee.handle,{backgroundColor:k.components.bottomSheet?.handleColor??k.colors.border.primary},p]})})}),null!=g&&(0,_jsxRuntime.jsx)(_reactNative.View,{style:[Ee.header,R],onLayout:q?z:void 0,children:g}),c?(0,_jsxRuntime.jsx)(_reactNativeGestureHandler.GestureDetector,{gesture:Me,children:(0,_jsxRuntime.jsx)(_reactNative.ScrollView,{ref:u,style:Ee.content,onScroll:d,onContentSizeChange:ee,onLayout:m,scrollEventThrottle:h,keyboardShouldPersistTaps:"always",keyboardDismissMode:"none",children:N})}):(0,_jsxRuntime.jsx)(_reactNative.View,{style:Ee.content,children:q?(0,_jsxRuntime.jsx)(_reactNative.View,{onLayout:$,children:N}):N}),null!=x&&(0,_jsxRuntime.jsx)(_reactNative.View,{style:[Ee.footer,y],onLayout:q?U:void 0,children:x})]})})]}),Je=(0,_jsxRuntime.jsx)(BottomSheetContext.Provider,{value:We,children:Fe});return"modal"===f?(0,_jsxRuntime.jsx)(_reactNative.Modal,{transparent:!0,visible:ue,onRequestClose:we,onDismiss:"ios"===_reactNative.Platform.OS?xe:void 0,statusBarTranslucent:!0,navigationBarTranslucent:!0,animationType:"none",supportedOrientations:["portrait","landscape"],children:(0,_jsxRuntime.jsxs)(_reactNativeSafeAreaContext.SafeAreaProvider,{style:Ee.modalRoot,children:[(0,_jsxRuntime.jsx)(InsetsProbe,{onChange:A}),"android"===_reactNative.Platform.OS?(0,_jsxRuntime.jsx)(_reactNativeGestureHandler.GestureHandlerRootView,{style:Ee.modalRoot,children:Je}):Je,(0,_jsxRuntime.jsx)(_ToastProvider.ToastHost,{})]})}):Je}),InsetsProbe=({onChange:e})=>{const{top:t,bottom:a}=(0,_reactNativeSafeAreaContext.useSafeAreaInsets)();return(0,_react.useEffect)(()=>{e(e=>e.top===t&&e.bottom===a?e:{top:t,bottom:a})},[t,a,e]),null},SheetBody=({style:e,keyboardOffset:t,children:a})=>{const r=(0,_reactNativeSafeAreaContext.useSafeAreaInsets)().bottom,o=(0,_reactNativeReanimated.useAnimatedStyle)(()=>{const e=r+t.value;return{paddingBottom:e>0?e:0}});return(0,_jsxRuntime.jsx)(_reactNativeReanimated.default.View,{style:[e,o],children:a})};BottomSheet.displayName="BottomSheet";const useMeasuredHeight=()=>{const[e,t]=(0,_react.useState)(0),a=(0,_react.useCallback)(e=>{t(t=>t===e?t:e)},[]);return[e,(0,_react.useCallback)(e=>a(e.nativeEvent.layout.height),[a]),a]},resolveSnapPoints=(e,t,a)=>[...e.map(e=>{if("number"==typeof e)return e;if("content"===e)return a;const r=parseFloat(e);return Number.isNaN(r)?0:r/100*t})].sort((e,t)=>e-t),clamp=(e,t,a)=>Math.min(Math.max(e,t),a),buildStyles=e=>_reactNative.StyleSheet.create({backdropModal:{flex:1},backdropInline:{..._reactNative.StyleSheet.absoluteFill},sheet:{position:"absolute",left:0,right:0,overflow:"hidden"},body:{overflow:"hidden"},handleRow:{alignItems:"center",justifyContent:"center",alignSelf:"stretch",paddingTop:12,paddingBottom:24},header:{},footer:{},handle:{width:36,height:4,borderRadius:2,..._corners.smoothCorners},content:{flex:1,overflow:"hidden"},modalRoot:{flex:1}});var _default=exports.default=BottomSheet;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.useBottomSheet=exports.default=exports.BottomSheet=void 0;var _react=_interopRequireWildcard(require("react")),_reactNative=require("react-native"),_reactNativeGestureHandler=require("react-native-gesture-handler"),_reactNativeKeyboardController=require("react-native-keyboard-controller"),_reactNativeReanimated=_interopRequireWildcard(require("react-native-reanimated")),_reactNativeSafeAreaContext=require("react-native-safe-area-context"),_index=require("../../theme/index.js"),_index2=require("../../utils/index.js"),_corners=require("../../utils/corners.js"),_ToastProvider=require("../Toast/ToastProvider.js"),_jsxRuntime=require("react/jsx-runtime");function _interopRequireWildcard(e,t){if("function"==typeof WeakMap)var a=new WeakMap,r=new WeakMap;return(_interopRequireWildcard=function(e,t){if(!t&&e&&e.__esModule)return e;var o,n,i={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return i;if(o=t?r:a){if(o.has(e))return o.get(e);o.set(e,i)}for(const t in e)"default"!==t&&{}.hasOwnProperty.call(e,t)&&((n=(o=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,t))&&(n.get||n.set)?o(i,t,n):i[t]=e[t]);return i})(e,t)}const TABLET_MIN_SHORT_SIDE=600,DIALOG_MAX_WIDTH=560,BottomSheetContext=(0,_react.createContext)(null),useBottomSheet=()=>{const e=(0,_react.useContext)(BottomSheetContext);if(!e)throw new Error("useBottomSheet must be used inside a <BottomSheet>.");return e};exports.useBottomSheet=useBottomSheet;const SPRING_CONFIG={damping:20,stiffness:240,mass:1},CLOSE_VELOCITY_THRESHOLD=1e3,DRAG_ACTIVATION_OFFSET=10,BottomSheet=exports.BottomSheet=(0,_react.forwardRef)((e,t)=>{const{snapPoints:a,index:r,onChange:o,onAnimate:n,onAfterClose:i,enablePanDownToClose:s=!0,enableBackdropPress:l=!0,scrollable:c=!1,scrollRef:u,onScroll:d,onContentSizeChange:_,onScrollLayout:m,scrollEventThrottle:h,keyboardBehavior:v="shift",mode:f="modal",presentation:b="sheet",handleIndicatorStyle:p,containerStyle:S,header:x,footer:g,headerStyle:R,footerStyle:y,children:N,accessibilityLabel:w,accessibilityViewIsModal:j,testID:C}=e,k=(0,_index.useTheme)(),I=(0,_reactNativeSafeAreaContext.useSafeAreaInsets)(),[M,O]=(0,_react.useState)(()=>_reactNative.Dimensions.get("window").height),[T,H]=(0,_react.useState)(()=>_reactNative.Dimensions.get("window").width),B=(0,_react.useCallback)(e=>{const{height:t,width:a}=e.nativeEvent.layout;t>0&&O(e=>e===t?e:t),a>0&&H(e=>e===a?e:a)},[]),P=(0,_reactNative.useWindowDimensions)(),G="dialog"===b||"auto"===b&&Math.min(P.width,P.height)>=600,D=Math.min(560,T-2*k.spacing.xl),[V,A]=(0,_react.useState)({top:I.top,bottom:I.bottom}),E="modal"===f?V.top:I.top,L="modal"===f?V.bottom:I.bottom,q=a.includes("content"),[W,F]=useMeasuredHeight(),[J,z]=useMeasuredHeight(),[Y,$,K]=useMeasuredHeight(),[X,U]=useMeasuredHeight(),Q=G?k.spacing.md:W,Z=q?Math.min(Q+(null!=x?J:0)+Y+(null!=g?X:0)+L,M-E):0,ee=(0,_react.useCallback)((e,t)=>{q&&K(t),_?.(e,t)},[q,_,K]),te=(0,_react.useMemo)(()=>resolveSnapPoints(a,M,Z),[a,M,Z]),ae=M,re=te[te.length-1]??0,oe=(0,_reactNativeReanimated.useSharedValue)(ae),ne=(0,_reactNativeReanimated.useSharedValue)(ae),ie=(0,_reactNativeReanimated.useSharedValue)(-1),[se,le]=(0,_react.useState)(-1),ce=(0,_react.useRef)(!1),[ue,de]=(0,_react.useState)(!1),[_e,me]=(0,_react.useState)(!1),he=(0,_react.useRef)(!1),ve=(0,_react.useRef)(i);ve.current=i;const[fe,be]=(0,_react.useState)(!1),pe=(0,_react.useCallback)(e=>{if(e<0||e>=te.length)return ae;const t=te[e];return G?(M-t)/2:M-t},[te,M,ae,G]),Se=(0,_react.useCallback)(e=>{se!==e&&(le(e),ie.value=e,o?.(e))},[se,ie,o]),xe=(0,_react.useCallback)(()=>{ce.current=!1,ie.value<0&&(he.current=!0,"modal"===f?(de(!1),"ios"!==_reactNative.Platform.OS&&me(!1)):be(!1))},[f,ie]),ge=(0,_react.useCallback)(()=>{he.current&&me(!1)},[]);(0,_react.useEffect)(()=>{("modal"===f?!_e:!fe)&&he.current&&(he.current=!1,ve.current?.())},[f,_e,fe]);const Re=(0,_react.useCallback)((e,t,a)=>{ce.current=!0,n?.(t,a),oe.value=(0,_reactNativeReanimated.withSpring)(e,SPRING_CONFIG,e=>{"worklet";e&&(0,_reactNativeReanimated.runOnJS)(xe)()})},[n,oe,xe]),ye=(0,_react.useCallback)(e=>{const t="number"==typeof e?clamp(e,0,te.length-1):se>=0?se:0,a=ie.value,r=pe(t);he.current=!1,"modal"===f?(me(!0),de(!0)):be(!0),a<0&&(oe.value=ae),Se(t),Re(r,a,t)},[Re,ae,se,ie,f,te.length,Se,oe,pe]),Ne=(0,_react.useCallback)(()=>{if(0===te.length)return;const e=ie.value,t=pe(0);Se(0),Re(t,e,0)},[Re,ie,te.length,Se,pe]),we=(0,_react.useCallback)(()=>{const e=ie.value;Se(-1),ce.current=!0,n?.(e,-1),oe.value=(0,_reactNativeReanimated.withTiming)(ae,{duration:k.motion.duration.fast,easing:_reactNativeReanimated.Easing.bezier(...k.motion.easing.accelerate)},e=>{"worklet";e&&(0,_reactNativeReanimated.runOnJS)(xe)()})},[ae,ie,xe,n,Se,oe,k.motion.duration.fast,k.motion.easing.accelerate]);(0,_react.useImperativeHandle)(t,()=>({expand:ye,collapse:Ne,close:we}),[ye,Ne,we]),(0,_react.useEffect)(()=>{"number"==typeof r&&r!==se&&(-1===r?we():ye(r))},[r]);const je=(0,_react.useRef)({hostHeight:M,contentSnap:Z});(0,_react.useEffect)(()=>{const e=je.current;e.hostHeight===M&&e.contentSnap===Z||(je.current={hostHeight:M,contentSnap:Z},e.hostHeight===M&&ie.value<0||(oe.value=(0,_reactNativeReanimated.withSpring)(pe(ie.value),SPRING_CONFIG)))},[M,Z]);const Ce=M-re,ke=(0,_react.useMemo)(()=>te.map(e=>M-e),[te,M]),Ie=(0,_react.useCallback)((e,t)=>{const a=ie.value;if(-1===e)return(0,_index2.triggerHaptic)("selection"),Se(-1),ce.current=!0,n?.(a,-1),void(oe.value=(0,_reactNativeReanimated.withTiming)(ae,{duration:k.motion.duration.fast,easing:_reactNativeReanimated.Easing.bezier(...k.motion.easing.accelerate)},e=>{"worklet";e&&(0,_reactNativeReanimated.runOnJS)(xe)()}));Se(e),Re(t,a,e)},[Re,ae,ie,xe,n,Se,oe,k.motion.duration.fast,k.motion.easing.accelerate]),Me=(0,_react.useMemo)(()=>_reactNativeGestureHandler.Gesture.Native().withTestId(C?`${C}-content-gesture`:"bottom-sheet-content-gesture"),[C]),Oe=(0,_react.useMemo)(()=>{const e=ke,t=ae,a=Ce,r=s;return _reactNativeGestureHandler.Gesture.Pan().withTestId(C?`${C}-pan-gesture`:"bottom-sheet-pan-gesture").activeOffsetY([-10,10]).failOffsetX([-15,15]).onStart(()=>{"worklet";ne.value=oe.value}).onUpdate(e=>{"worklet";const t=ne.value+e.translationY;oe.value=t<a?a+.25*(t-a):t}).onEnd(a=>{"worklet";const o=oe.value;if(a.velocityY>1e3)return r?void(0,_reactNativeReanimated.runOnJS)(Ie)(-1,t):void(0,_reactNativeReanimated.runOnJS)(Ie)(0,e[0]);let n=0,i=Math.abs(o-e[0]);for(let t=1;t<e.length;t++){const a=Math.abs(o-e[t]);a<i&&(i=a,n=t)}const s=e[0];r&&o-s>80?(0,_reactNativeReanimated.runOnJS)(Ie)(-1,t):(0,_reactNativeReanimated.runOnJS)(Ie)(n,e[n])})},[ae,ne,s,Ie,Ce,ke,C,oe]),{height:Te}=(0,_reactNativeKeyboardController.useReanimatedKeyboardAnimation)(),He="shift"===v,Be=(0,_reactNativeReanimated.useDerivedValue)(()=>He?Te.value:0),Pe=te[se>=0?se:0]??re,Ge=k.spacing.md,De=(0,_reactNativeReanimated.useAnimatedStyle)(()=>{if(G){const e=Be.value,t=M+e-Pe-Ge,a=e<0&&oe.value>t?t:oe.value;return{top:a<E?E:a}}const e=oe.value+Be.value,t=Be.value<0?E:Ce;return{top:e<t?t:e}}),Ve=(0,_reactNativeReanimated.useAnimatedStyle)(()=>{const e=Be.value;if(G){const t=M+e-Pe-Ge,a=e<0&&oe.value>t?t:oe.value,r=M+e-Ge-(a<E?E:a);return{height:r<0?0:r>Pe?Pe:r}}const t=e<0?E:Ce,a=oe.value+e,r=M+e-(a<t?t:a);return{height:r<0?0:r>re?re:r}}),Ae=se>=0,Ee=(0,_react.useMemo)(()=>buildStyles(k),[k]),Le=(0,_react.useCallback)(()=>{l&&((0,_index2.triggerHaptic)("selection"),we())},[l,we]),qe=(0,_react.useMemo)(()=>_reactNativeGestureHandler.Gesture.Tap().withTestId(C?`${C}-backdrop-gesture`:"bottom-sheet-backdrop-gesture").maxDuration(250).onEnd((e,t)=>{"worklet";t&&(0,_reactNativeReanimated.runOnJS)(Le)()}),[Le,C]),We=(0,_react.useMemo)(()=>({snapIndex:se,snapPoints:te,expand:ye,collapse:Ne,close:we}),[se,te,ye,Ne,we]);if("inline"===f&&!fe)return null;if("modal"===f&&!_e)return null;const Fe=(0,_jsxRuntime.jsxs)(_reactNative.View,{collapsable:!1,style:["modal"===f?Ee.backdropModal:Ee.backdropInline,{backgroundColor:k.colors.background.overlay}],onLayout:B,testID:C,accessibilityViewIsModal:j??Ae,children:[(0,_jsxRuntime.jsx)(_reactNativeGestureHandler.GestureDetector,{gesture:qe,children:(0,_jsxRuntime.jsx)(_reactNativeReanimated.default.View,{style:_reactNative.StyleSheet.absoluteFill,accessibilityRole:"button",accessibilityLabel:"Close bottom sheet"})}),(0,_jsxRuntime.jsx)(_reactNativeReanimated.default.View,{accessibilityRole:"alert",accessibilityLabel:w,accessibilityViewIsModal:j??Ae,style:[Ee.sheet,{height:re,backgroundColor:k.colors.background.elevated,borderTopLeftRadius:k.radius["2xl"],borderTopRightRadius:k.radius["2xl"],..._corners.smoothCorners,...k.shadows.xl},G?{height:Pe,left:(T-D)/2,right:void 0,width:D,borderBottomLeftRadius:k.radius["2xl"],borderBottomRightRadius:k.radius["2xl"]}:null,S,De],children:(0,_jsxRuntime.jsxs)(SheetBody,{style:[Ee.body,Ve],keyboardOffset:Be,children:[G?(0,_jsxRuntime.jsx)(_reactNative.View,{style:{height:k.spacing.md}}):(0,_jsxRuntime.jsx)(_reactNativeGestureHandler.GestureDetector,{gesture:Oe,children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:Ee.handleRow,onLayout:q?F:void 0,accessible:!0,accessibilityLabel:"Drag handle",accessibilityHint:"Drag up or down to resize the sheet, or swipe down to close it",testID:C?`${C}-handle`:"bottom-sheet-handle",children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:[Ee.handle,{backgroundColor:k.components.bottomSheet?.handleColor??k.colors.border.primary},p]})})}),null!=x&&(0,_jsxRuntime.jsx)(_reactNative.View,{style:[Ee.header,R],onLayout:q?z:void 0,children:x}),c?(0,_jsxRuntime.jsx)(_reactNativeGestureHandler.GestureDetector,{gesture:Me,children:(0,_jsxRuntime.jsx)(_reactNative.ScrollView,{ref:u,style:Ee.scrollContent,onScroll:d,onContentSizeChange:ee,onLayout:m,scrollEventThrottle:h,keyboardShouldPersistTaps:"always",keyboardDismissMode:"none",children:N})}):(0,_jsxRuntime.jsx)(_reactNative.View,{style:Ee.content,children:q?(0,_jsxRuntime.jsx)(_reactNative.View,{onLayout:$,children:N}):N}),null!=g&&(0,_jsxRuntime.jsx)(_reactNative.View,{style:[Ee.footer,y],onLayout:q?U:void 0,children:g})]})})]}),Je=(0,_jsxRuntime.jsx)(BottomSheetContext.Provider,{value:We,children:Fe});return"modal"===f?(0,_jsxRuntime.jsx)(_reactNative.Modal,{transparent:!0,visible:ue,onRequestClose:we,onDismiss:"ios"===_reactNative.Platform.OS?ge:void 0,statusBarTranslucent:!0,navigationBarTranslucent:!0,animationType:"none",supportedOrientations:["portrait","landscape"],children:(0,_jsxRuntime.jsxs)(_reactNativeSafeAreaContext.SafeAreaProvider,{style:Ee.modalRoot,children:[(0,_jsxRuntime.jsx)(InsetsProbe,{onChange:A}),"android"===_reactNative.Platform.OS?(0,_jsxRuntime.jsx)(_reactNativeGestureHandler.GestureHandlerRootView,{style:Ee.modalRoot,children:Je}):Je,(0,_jsxRuntime.jsx)(_ToastProvider.ToastHost,{})]})}):Je}),InsetsProbe=({onChange:e})=>{const{top:t,bottom:a}=(0,_reactNativeSafeAreaContext.useSafeAreaInsets)();return(0,_react.useEffect)(()=>{e(e=>e.top===t&&e.bottom===a?e:{top:t,bottom:a})},[t,a,e]),null},SheetBody=({style:e,keyboardOffset:t,children:a})=>{const r=(0,_reactNativeSafeAreaContext.useSafeAreaInsets)().bottom,o=(0,_reactNativeReanimated.useAnimatedStyle)(()=>{const e=r+t.value;return{paddingBottom:e>0?e:0}});return(0,_jsxRuntime.jsx)(_reactNativeReanimated.default.View,{style:[e,o],children:a})};BottomSheet.displayName="BottomSheet";const useMeasuredHeight=()=>{const[e,t]=(0,_react.useState)(0),a=(0,_react.useCallback)(e=>{t(t=>t===e?t:e)},[]);return[e,(0,_react.useCallback)(e=>a(e.nativeEvent.layout.height),[a]),a]},resolveSnapPoints=(e,t,a)=>[...e.map(e=>{if("number"==typeof e)return e;if("content"===e)return a;const r=parseFloat(e);return Number.isNaN(r)?0:r/100*t})].sort((e,t)=>e-t),clamp=(e,t,a)=>Math.min(Math.max(e,t),a),buildStyles=e=>_reactNative.StyleSheet.create({backdropModal:{flex:1},backdropInline:{..._reactNative.StyleSheet.absoluteFill},sheet:{position:"absolute",left:0,right:0,overflow:"hidden"},body:{overflow:"hidden"},handleRow:{alignItems:"center",justifyContent:"center",alignSelf:"stretch",paddingTop:12,paddingBottom:24},header:{},footer:{},handle:{width:36,height:4,borderRadius:2,..._corners.smoothCorners},content:{flex:1,overflow:"hidden"},scrollContent:{flex:1},modalRoot:{flex:1}});var _default=exports.default=BottomSheet;
@@ -1 +1 @@
1
- "use strict";import React,{createContext,forwardRef,useCallback,useContext,useEffect,useImperativeHandle,useMemo,useRef,useState}from"react";import{Dimensions,Modal,Platform,ScrollView,StyleSheet,useWindowDimensions,View}from"react-native";import{Gesture,GestureDetector,GestureHandlerRootView}from"react-native-gesture-handler";import{useReanimatedKeyboardAnimation}from"react-native-keyboard-controller";import Animated,{Easing,runOnJS,useAnimatedStyle,useDerivedValue,useSharedValue,withSpring,withTiming}from"react-native-reanimated";import{SafeAreaProvider,useSafeAreaInsets}from"react-native-safe-area-context";import{useTheme}from"../../theme/index.js";import{triggerHaptic}from"../../utils/index.js";import{smoothCorners}from"../../utils/corners.js";import{ToastHost}from"../Toast/ToastProvider.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const TABLET_MIN_SHORT_SIDE=600,DIALOG_MAX_WIDTH=560,BottomSheetContext=createContext(null);export const useBottomSheet=()=>{const e=useContext(BottomSheetContext);if(!e)throw new Error("useBottomSheet must be used inside a <BottomSheet>.");return e};const SPRING_CONFIG={damping:20,stiffness:240,mass:1},CLOSE_VELOCITY_THRESHOLD=1e3,DRAG_ACTIVATION_OFFSET=10,BottomSheet=forwardRef((e,t)=>{const{snapPoints:o,index:s,onChange:n,onAnimate:a,onAfterClose:r,enablePanDownToClose:i=!0,enableBackdropPress:l=!0,scrollable:u=!1,scrollRef:c,onScroll:d,onContentSizeChange:h,onScrollLayout:m,scrollEventThrottle:b,keyboardBehavior:f="shift",mode:S="modal",presentation:g="sheet",handleIndicatorStyle:p,containerStyle:v,header:y,footer:w,headerStyle:x,footerStyle:C,children:k,accessibilityLabel:_,accessibilityViewIsModal:I,testID:R}=e,j=useTheme(),T=useSafeAreaInsets(),[M,O]=useState(()=>Dimensions.get("window").height),[V,D]=useState(()=>Dimensions.get("window").width),A=useCallback(e=>{const{height:t,width:o}=e.nativeEvent.layout;t>0&&O(e=>e===t?e:t),o>0&&D(e=>e===o?e:o)},[]),H=useWindowDimensions(),B="dialog"===g||"auto"===g&&Math.min(H.width,H.height)>=600,E=Math.min(560,V-2*j.spacing.xl),[P,G]=useState({top:T.top,bottom:T.bottom}),L="modal"===S?P.top:T.top,N="modal"===S?P.bottom:T.bottom,J=o.includes("content"),[F,z]=useMeasuredHeight(),[Y,$]=useMeasuredHeight(),[W,K,X]=useMeasuredHeight(),[q,U]=useMeasuredHeight(),Q=B?j.spacing.md:F,Z=J?Math.min(Q+(null!=y?Y:0)+W+(null!=w?q:0)+N,M-L):0,ee=useCallback((e,t)=>{J&&X(t),h?.(e,t)},[J,h,X]),te=useMemo(()=>resolveSnapPoints(o,M,Z),[o,M,Z]),oe=M,se=te[te.length-1]??0,ne=useSharedValue(oe),ae=useSharedValue(oe),re=useSharedValue(-1),[ie,le]=useState(-1),ue=useRef(!1),[ce,de]=useState(!1),[he,me]=useState(!1),be=useRef(!1),fe=useRef(r);fe.current=r;const[Se,ge]=useState(!1),pe=useCallback(e=>{if(e<0||e>=te.length)return oe;const t=te[e];return B?(M-t)/2:M-t},[te,M,oe,B]),ve=useCallback(e=>{ie!==e&&(le(e),re.value=e,n?.(e))},[ie,re,n]),ye=useCallback(()=>{ue.current=!1,re.value<0&&(be.current=!0,"modal"===S?(de(!1),"ios"!==Platform.OS&&me(!1)):ge(!1))},[S,re]),we=useCallback(()=>{be.current&&me(!1)},[]);useEffect(()=>{("modal"===S?!he:!Se)&&be.current&&(be.current=!1,fe.current?.())},[S,he,Se]);const xe=useCallback((e,t,o)=>{ue.current=!0,a?.(t,o),ne.value=withSpring(e,SPRING_CONFIG,e=>{"worklet";e&&runOnJS(ye)()})},[a,ne,ye]),Ce=useCallback(e=>{const t="number"==typeof e?clamp(e,0,te.length-1):ie>=0?ie:0,o=re.value,s=pe(t);be.current=!1,"modal"===S?(me(!0),de(!0)):ge(!0),o<0&&(ne.value=oe),ve(t),xe(s,o,t)},[xe,oe,ie,re,S,te.length,ve,ne,pe]),ke=useCallback(()=>{if(0===te.length)return;const e=re.value,t=pe(0);ve(0),xe(t,e,0)},[xe,re,te.length,ve,pe]),_e=useCallback(()=>{const e=re.value;ve(-1),ue.current=!0,a?.(e,-1),ne.value=withTiming(oe,{duration:j.motion.duration.fast,easing:Easing.bezier(...j.motion.easing.accelerate)},e=>{"worklet";e&&runOnJS(ye)()})},[oe,re,ye,a,ve,ne,j.motion.duration.fast,j.motion.easing.accelerate]);useImperativeHandle(t,()=>({expand:Ce,collapse:ke,close:_e}),[Ce,ke,_e]),useEffect(()=>{"number"==typeof s&&s!==ie&&(-1===s?_e():Ce(s))},[s]);const Ie=useRef({hostHeight:M,contentSnap:Z});useEffect(()=>{const e=Ie.current;e.hostHeight===M&&e.contentSnap===Z||(Ie.current={hostHeight:M,contentSnap:Z},e.hostHeight===M&&re.value<0||(ne.value=withSpring(pe(re.value),SPRING_CONFIG)))},[M,Z]);const Re=M-se,je=useMemo(()=>te.map(e=>M-e),[te,M]),Te=useCallback((e,t)=>{const o=re.value;if(-1===e)return triggerHaptic("selection"),ve(-1),ue.current=!0,a?.(o,-1),void(ne.value=withTiming(oe,{duration:j.motion.duration.fast,easing:Easing.bezier(...j.motion.easing.accelerate)},e=>{"worklet";e&&runOnJS(ye)()}));ve(e),xe(t,o,e)},[xe,oe,re,ye,a,ve,ne,j.motion.duration.fast,j.motion.easing.accelerate]),Me=useMemo(()=>Gesture.Native().withTestId(R?`${R}-content-gesture`:"bottom-sheet-content-gesture"),[R]),Oe=useMemo(()=>{const e=je,t=oe,o=Re,s=i;return Gesture.Pan().withTestId(R?`${R}-pan-gesture`:"bottom-sheet-pan-gesture").activeOffsetY([-10,10]).failOffsetX([-15,15]).onStart(()=>{"worklet";ae.value=ne.value}).onUpdate(e=>{"worklet";const t=ae.value+e.translationY;ne.value=t<o?o+.25*(t-o):t}).onEnd(o=>{"worklet";const n=ne.value;if(o.velocityY>1e3)return s?void runOnJS(Te)(-1,t):void runOnJS(Te)(0,e[0]);let a=0,r=Math.abs(n-e[0]);for(let t=1;t<e.length;t++){const o=Math.abs(n-e[t]);o<r&&(r=o,a=t)}const i=e[0];s&&n-i>80?runOnJS(Te)(-1,t):runOnJS(Te)(a,e[a])})},[oe,ae,i,Te,Re,je,R,ne]),{height:Ve}=useReanimatedKeyboardAnimation(),De="shift"===f,Ae=useDerivedValue(()=>De?Ve.value:0),He=te[ie>=0?ie:0]??se,Be=j.spacing.md,Ee=useAnimatedStyle(()=>{if(B){const e=Ae.value,t=M+e-He-Be,o=e<0&&ne.value>t?t:ne.value;return{top:o<L?L:o}}const e=ne.value+Ae.value,t=Ae.value<0?L:Re;return{top:e<t?t:e}}),Pe=useAnimatedStyle(()=>{const e=Ae.value;if(B){const t=M+e-He-Be,o=e<0&&ne.value>t?t:ne.value,s=M+e-Be-(o<L?L:o);return{height:s<0?0:s>He?He:s}}const t=e<0?L:Re,o=ne.value+e,s=M+e-(o<t?t:o);return{height:s<0?0:s>se?se:s}}),Ge=ie>=0,Le=useMemo(()=>buildStyles(j),[j]),Ne=useCallback(()=>{l&&(triggerHaptic("selection"),_e())},[l,_e]),Je=useMemo(()=>Gesture.Tap().withTestId(R?`${R}-backdrop-gesture`:"bottom-sheet-backdrop-gesture").maxDuration(250).onEnd((e,t)=>{"worklet";t&&runOnJS(Ne)()}),[Ne,R]),Fe=useMemo(()=>({snapIndex:ie,snapPoints:te,expand:Ce,collapse:ke,close:_e}),[ie,te,Ce,ke,_e]);if("inline"===S&&!Se)return null;if("modal"===S&&!he)return null;const ze=_jsxs(View,{collapsable:!1,style:["modal"===S?Le.backdropModal:Le.backdropInline,{backgroundColor:j.colors.background.overlay}],onLayout:A,testID:R,accessibilityViewIsModal:I??Ge,children:[_jsx(GestureDetector,{gesture:Je,children:_jsx(Animated.View,{style:StyleSheet.absoluteFill,accessibilityRole:"button",accessibilityLabel:"Close bottom sheet"})}),_jsx(Animated.View,{accessibilityRole:"alert",accessibilityLabel:_,accessibilityViewIsModal:I??Ge,style:[Le.sheet,{height:se,backgroundColor:j.colors.background.elevated,borderTopLeftRadius:j.radius["2xl"],borderTopRightRadius:j.radius["2xl"],...smoothCorners,...j.shadows.xl},B?{height:He,left:(V-E)/2,right:void 0,width:E,borderBottomLeftRadius:j.radius["2xl"],borderBottomRightRadius:j.radius["2xl"]}:null,v,Ee],children:_jsxs(SheetBody,{style:[Le.body,Pe],keyboardOffset:Ae,children:[B?_jsx(View,{style:{height:j.spacing.md}}):_jsx(GestureDetector,{gesture:Oe,children:_jsx(View,{style:Le.handleRow,onLayout:J?z:void 0,accessible:!0,accessibilityLabel:"Drag handle",accessibilityHint:"Drag up or down to resize the sheet, or swipe down to close it",testID:R?`${R}-handle`:"bottom-sheet-handle",children:_jsx(View,{style:[Le.handle,{backgroundColor:j.components.bottomSheet?.handleColor??j.colors.border.primary},p]})})}),null!=y&&_jsx(View,{style:[Le.header,x],onLayout:J?$:void 0,children:y}),u?_jsx(GestureDetector,{gesture:Me,children:_jsx(ScrollView,{ref:c,style:Le.content,onScroll:d,onContentSizeChange:ee,onLayout:m,scrollEventThrottle:b,keyboardShouldPersistTaps:"always",keyboardDismissMode:"none",children:k})}):_jsx(View,{style:Le.content,children:J?_jsx(View,{onLayout:K,children:k}):k}),null!=w&&_jsx(View,{style:[Le.footer,C],onLayout:J?U:void 0,children:w})]})})]}),Ye=_jsx(BottomSheetContext.Provider,{value:Fe,children:ze});return"modal"===S?_jsx(Modal,{transparent:!0,visible:ce,onRequestClose:_e,onDismiss:"ios"===Platform.OS?we:void 0,statusBarTranslucent:!0,navigationBarTranslucent:!0,animationType:"none",supportedOrientations:["portrait","landscape"],children:_jsxs(SafeAreaProvider,{style:Le.modalRoot,children:[_jsx(InsetsProbe,{onChange:G}),"android"===Platform.OS?_jsx(GestureHandlerRootView,{style:Le.modalRoot,children:Ye}):Ye,_jsx(ToastHost,{})]})}):Ye}),InsetsProbe=({onChange:e})=>{const{top:t,bottom:o}=useSafeAreaInsets();return useEffect(()=>{e(e=>e.top===t&&e.bottom===o?e:{top:t,bottom:o})},[t,o,e]),null},SheetBody=({style:e,keyboardOffset:t,children:o})=>{const s=useSafeAreaInsets().bottom,n=useAnimatedStyle(()=>{const e=s+t.value;return{paddingBottom:e>0?e:0}});return _jsx(Animated.View,{style:[e,n],children:o})};BottomSheet.displayName="BottomSheet";const useMeasuredHeight=()=>{const[e,t]=useState(0),o=useCallback(e=>{t(t=>t===e?t:e)},[]);return[e,useCallback(e=>o(e.nativeEvent.layout.height),[o]),o]},resolveSnapPoints=(e,t,o)=>[...e.map(e=>{if("number"==typeof e)return e;if("content"===e)return o;const s=parseFloat(e);return Number.isNaN(s)?0:s/100*t})].sort((e,t)=>e-t),clamp=(e,t,o)=>Math.min(Math.max(e,t),o),buildStyles=e=>StyleSheet.create({backdropModal:{flex:1},backdropInline:{...StyleSheet.absoluteFill},sheet:{position:"absolute",left:0,right:0,overflow:"hidden"},body:{overflow:"hidden"},handleRow:{alignItems:"center",justifyContent:"center",alignSelf:"stretch",paddingTop:12,paddingBottom:24},header:{},footer:{},handle:{width:36,height:4,borderRadius:2,...smoothCorners},content:{flex:1,overflow:"hidden"},modalRoot:{flex:1}});export{BottomSheet};export default BottomSheet;
1
+ "use strict";import React,{createContext,forwardRef,useCallback,useContext,useEffect,useImperativeHandle,useMemo,useRef,useState}from"react";import{Dimensions,Modal,Platform,ScrollView,StyleSheet,useWindowDimensions,View}from"react-native";import{Gesture,GestureDetector,GestureHandlerRootView}from"react-native-gesture-handler";import{useReanimatedKeyboardAnimation}from"react-native-keyboard-controller";import Animated,{Easing,runOnJS,useAnimatedStyle,useDerivedValue,useSharedValue,withSpring,withTiming}from"react-native-reanimated";import{SafeAreaProvider,useSafeAreaInsets}from"react-native-safe-area-context";import{useTheme}from"../../theme/index.js";import{triggerHaptic}from"../../utils/index.js";import{smoothCorners}from"../../utils/corners.js";import{ToastHost}from"../Toast/ToastProvider.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const TABLET_MIN_SHORT_SIDE=600,DIALOG_MAX_WIDTH=560,BottomSheetContext=createContext(null);export const useBottomSheet=()=>{const e=useContext(BottomSheetContext);if(!e)throw new Error("useBottomSheet must be used inside a <BottomSheet>.");return e};const SPRING_CONFIG={damping:20,stiffness:240,mass:1},CLOSE_VELOCITY_THRESHOLD=1e3,DRAG_ACTIVATION_OFFSET=10,BottomSheet=forwardRef((e,t)=>{const{snapPoints:o,index:s,onChange:n,onAnimate:a,onAfterClose:r,enablePanDownToClose:i=!0,enableBackdropPress:l=!0,scrollable:u=!1,scrollRef:c,onScroll:d,onContentSizeChange:h,onScrollLayout:m,scrollEventThrottle:f,keyboardBehavior:b="shift",mode:S="modal",presentation:g="sheet",handleIndicatorStyle:p,containerStyle:v,header:y,footer:w,headerStyle:x,footerStyle:C,children:k,accessibilityLabel:_,accessibilityViewIsModal:I,testID:R}=e,j=useTheme(),T=useSafeAreaInsets(),[M,O]=useState(()=>Dimensions.get("window").height),[V,D]=useState(()=>Dimensions.get("window").width),A=useCallback(e=>{const{height:t,width:o}=e.nativeEvent.layout;t>0&&O(e=>e===t?e:t),o>0&&D(e=>e===o?e:o)},[]),H=useWindowDimensions(),B="dialog"===g||"auto"===g&&Math.min(H.width,H.height)>=600,E=Math.min(560,V-2*j.spacing.xl),[P,G]=useState({top:T.top,bottom:T.bottom}),L="modal"===S?P.top:T.top,N="modal"===S?P.bottom:T.bottom,J=o.includes("content"),[F,z]=useMeasuredHeight(),[Y,$]=useMeasuredHeight(),[W,K,X]=useMeasuredHeight(),[q,U]=useMeasuredHeight(),Q=B?j.spacing.md:F,Z=J?Math.min(Q+(null!=y?Y:0)+W+(null!=w?q:0)+N,M-L):0,ee=useCallback((e,t)=>{J&&X(t),h?.(e,t)},[J,h,X]),te=useMemo(()=>resolveSnapPoints(o,M,Z),[o,M,Z]),oe=M,se=te[te.length-1]??0,ne=useSharedValue(oe),ae=useSharedValue(oe),re=useSharedValue(-1),[ie,le]=useState(-1),ue=useRef(!1),[ce,de]=useState(!1),[he,me]=useState(!1),fe=useRef(!1),be=useRef(r);be.current=r;const[Se,ge]=useState(!1),pe=useCallback(e=>{if(e<0||e>=te.length)return oe;const t=te[e];return B?(M-t)/2:M-t},[te,M,oe,B]),ve=useCallback(e=>{ie!==e&&(le(e),re.value=e,n?.(e))},[ie,re,n]),ye=useCallback(()=>{ue.current=!1,re.value<0&&(fe.current=!0,"modal"===S?(de(!1),"ios"!==Platform.OS&&me(!1)):ge(!1))},[S,re]),we=useCallback(()=>{fe.current&&me(!1)},[]);useEffect(()=>{("modal"===S?!he:!Se)&&fe.current&&(fe.current=!1,be.current?.())},[S,he,Se]);const xe=useCallback((e,t,o)=>{ue.current=!0,a?.(t,o),ne.value=withSpring(e,SPRING_CONFIG,e=>{"worklet";e&&runOnJS(ye)()})},[a,ne,ye]),Ce=useCallback(e=>{const t="number"==typeof e?clamp(e,0,te.length-1):ie>=0?ie:0,o=re.value,s=pe(t);fe.current=!1,"modal"===S?(me(!0),de(!0)):ge(!0),o<0&&(ne.value=oe),ve(t),xe(s,o,t)},[xe,oe,ie,re,S,te.length,ve,ne,pe]),ke=useCallback(()=>{if(0===te.length)return;const e=re.value,t=pe(0);ve(0),xe(t,e,0)},[xe,re,te.length,ve,pe]),_e=useCallback(()=>{const e=re.value;ve(-1),ue.current=!0,a?.(e,-1),ne.value=withTiming(oe,{duration:j.motion.duration.fast,easing:Easing.bezier(...j.motion.easing.accelerate)},e=>{"worklet";e&&runOnJS(ye)()})},[oe,re,ye,a,ve,ne,j.motion.duration.fast,j.motion.easing.accelerate]);useImperativeHandle(t,()=>({expand:Ce,collapse:ke,close:_e}),[Ce,ke,_e]),useEffect(()=>{"number"==typeof s&&s!==ie&&(-1===s?_e():Ce(s))},[s]);const Ie=useRef({hostHeight:M,contentSnap:Z});useEffect(()=>{const e=Ie.current;e.hostHeight===M&&e.contentSnap===Z||(Ie.current={hostHeight:M,contentSnap:Z},e.hostHeight===M&&re.value<0||(ne.value=withSpring(pe(re.value),SPRING_CONFIG)))},[M,Z]);const Re=M-se,je=useMemo(()=>te.map(e=>M-e),[te,M]),Te=useCallback((e,t)=>{const o=re.value;if(-1===e)return triggerHaptic("selection"),ve(-1),ue.current=!0,a?.(o,-1),void(ne.value=withTiming(oe,{duration:j.motion.duration.fast,easing:Easing.bezier(...j.motion.easing.accelerate)},e=>{"worklet";e&&runOnJS(ye)()}));ve(e),xe(t,o,e)},[xe,oe,re,ye,a,ve,ne,j.motion.duration.fast,j.motion.easing.accelerate]),Me=useMemo(()=>Gesture.Native().withTestId(R?`${R}-content-gesture`:"bottom-sheet-content-gesture"),[R]),Oe=useMemo(()=>{const e=je,t=oe,o=Re,s=i;return Gesture.Pan().withTestId(R?`${R}-pan-gesture`:"bottom-sheet-pan-gesture").activeOffsetY([-10,10]).failOffsetX([-15,15]).onStart(()=>{"worklet";ae.value=ne.value}).onUpdate(e=>{"worklet";const t=ae.value+e.translationY;ne.value=t<o?o+.25*(t-o):t}).onEnd(o=>{"worklet";const n=ne.value;if(o.velocityY>1e3)return s?void runOnJS(Te)(-1,t):void runOnJS(Te)(0,e[0]);let a=0,r=Math.abs(n-e[0]);for(let t=1;t<e.length;t++){const o=Math.abs(n-e[t]);o<r&&(r=o,a=t)}const i=e[0];s&&n-i>80?runOnJS(Te)(-1,t):runOnJS(Te)(a,e[a])})},[oe,ae,i,Te,Re,je,R,ne]),{height:Ve}=useReanimatedKeyboardAnimation(),De="shift"===b,Ae=useDerivedValue(()=>De?Ve.value:0),He=te[ie>=0?ie:0]??se,Be=j.spacing.md,Ee=useAnimatedStyle(()=>{if(B){const e=Ae.value,t=M+e-He-Be,o=e<0&&ne.value>t?t:ne.value;return{top:o<L?L:o}}const e=ne.value+Ae.value,t=Ae.value<0?L:Re;return{top:e<t?t:e}}),Pe=useAnimatedStyle(()=>{const e=Ae.value;if(B){const t=M+e-He-Be,o=e<0&&ne.value>t?t:ne.value,s=M+e-Be-(o<L?L:o);return{height:s<0?0:s>He?He:s}}const t=e<0?L:Re,o=ne.value+e,s=M+e-(o<t?t:o);return{height:s<0?0:s>se?se:s}}),Ge=ie>=0,Le=useMemo(()=>buildStyles(j),[j]),Ne=useCallback(()=>{l&&(triggerHaptic("selection"),_e())},[l,_e]),Je=useMemo(()=>Gesture.Tap().withTestId(R?`${R}-backdrop-gesture`:"bottom-sheet-backdrop-gesture").maxDuration(250).onEnd((e,t)=>{"worklet";t&&runOnJS(Ne)()}),[Ne,R]),Fe=useMemo(()=>({snapIndex:ie,snapPoints:te,expand:Ce,collapse:ke,close:_e}),[ie,te,Ce,ke,_e]);if("inline"===S&&!Se)return null;if("modal"===S&&!he)return null;const ze=_jsxs(View,{collapsable:!1,style:["modal"===S?Le.backdropModal:Le.backdropInline,{backgroundColor:j.colors.background.overlay}],onLayout:A,testID:R,accessibilityViewIsModal:I??Ge,children:[_jsx(GestureDetector,{gesture:Je,children:_jsx(Animated.View,{style:StyleSheet.absoluteFill,accessibilityRole:"button",accessibilityLabel:"Close bottom sheet"})}),_jsx(Animated.View,{accessibilityRole:"alert",accessibilityLabel:_,accessibilityViewIsModal:I??Ge,style:[Le.sheet,{height:se,backgroundColor:j.colors.background.elevated,borderTopLeftRadius:j.radius["2xl"],borderTopRightRadius:j.radius["2xl"],...smoothCorners,...j.shadows.xl},B?{height:He,left:(V-E)/2,right:void 0,width:E,borderBottomLeftRadius:j.radius["2xl"],borderBottomRightRadius:j.radius["2xl"]}:null,v,Ee],children:_jsxs(SheetBody,{style:[Le.body,Pe],keyboardOffset:Ae,children:[B?_jsx(View,{style:{height:j.spacing.md}}):_jsx(GestureDetector,{gesture:Oe,children:_jsx(View,{style:Le.handleRow,onLayout:J?z:void 0,accessible:!0,accessibilityLabel:"Drag handle",accessibilityHint:"Drag up or down to resize the sheet, or swipe down to close it",testID:R?`${R}-handle`:"bottom-sheet-handle",children:_jsx(View,{style:[Le.handle,{backgroundColor:j.components.bottomSheet?.handleColor??j.colors.border.primary},p]})})}),null!=y&&_jsx(View,{style:[Le.header,x],onLayout:J?$:void 0,children:y}),u?_jsx(GestureDetector,{gesture:Me,children:_jsx(ScrollView,{ref:c,style:Le.scrollContent,onScroll:d,onContentSizeChange:ee,onLayout:m,scrollEventThrottle:f,keyboardShouldPersistTaps:"always",keyboardDismissMode:"none",children:k})}):_jsx(View,{style:Le.content,children:J?_jsx(View,{onLayout:K,children:k}):k}),null!=w&&_jsx(View,{style:[Le.footer,C],onLayout:J?U:void 0,children:w})]})})]}),Ye=_jsx(BottomSheetContext.Provider,{value:Fe,children:ze});return"modal"===S?_jsx(Modal,{transparent:!0,visible:ce,onRequestClose:_e,onDismiss:"ios"===Platform.OS?we:void 0,statusBarTranslucent:!0,navigationBarTranslucent:!0,animationType:"none",supportedOrientations:["portrait","landscape"],children:_jsxs(SafeAreaProvider,{style:Le.modalRoot,children:[_jsx(InsetsProbe,{onChange:G}),"android"===Platform.OS?_jsx(GestureHandlerRootView,{style:Le.modalRoot,children:Ye}):Ye,_jsx(ToastHost,{})]})}):Ye}),InsetsProbe=({onChange:e})=>{const{top:t,bottom:o}=useSafeAreaInsets();return useEffect(()=>{e(e=>e.top===t&&e.bottom===o?e:{top:t,bottom:o})},[t,o,e]),null},SheetBody=({style:e,keyboardOffset:t,children:o})=>{const s=useSafeAreaInsets().bottom,n=useAnimatedStyle(()=>{const e=s+t.value;return{paddingBottom:e>0?e:0}});return _jsx(Animated.View,{style:[e,n],children:o})};BottomSheet.displayName="BottomSheet";const useMeasuredHeight=()=>{const[e,t]=useState(0),o=useCallback(e=>{t(t=>t===e?t:e)},[]);return[e,useCallback(e=>o(e.nativeEvent.layout.height),[o]),o]},resolveSnapPoints=(e,t,o)=>[...e.map(e=>{if("number"==typeof e)return e;if("content"===e)return o;const s=parseFloat(e);return Number.isNaN(s)?0:s/100*t})].sort((e,t)=>e-t),clamp=(e,t,o)=>Math.min(Math.max(e,t),o),buildStyles=e=>StyleSheet.create({backdropModal:{flex:1},backdropInline:{...StyleSheet.absoluteFill},sheet:{position:"absolute",left:0,right:0,overflow:"hidden"},body:{overflow:"hidden"},handleRow:{alignItems:"center",justifyContent:"center",alignSelf:"stretch",paddingTop:12,paddingBottom:24},header:{},footer:{},handle:{width:36,height:4,borderRadius:2,...smoothCorners},content:{flex:1,overflow:"hidden"},scrollContent:{flex:1},modalRoot:{flex:1}});export{BottomSheet};export default BottomSheet;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webority/mobile-ui",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Beautiful, animated, accessible React Native components, theme and form engine for Webority projects.",
5
5
  "keywords": [
6
6
  "react-native",
@@ -68,7 +68,7 @@
68
68
  "typecheck": "tsc --noEmit"
69
69
  },
70
70
  "peerDependencies": {
71
- "@webority/mobile-core": ">=0.2.0 <0.3.0",
71
+ "@webority/mobile-core": ">=0.3.0 <0.4.0",
72
72
  "expo": ">=57.0.0",
73
73
  "expo-file-system": ">=57.0.0",
74
74
  "expo-haptics": ">=57.0.0",