react-native-quick-preview 1.0.4 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # react-native-quicklook
1
+ # react-native-quick-preview
2
2
 
3
3
  A beautiful, customizable quick preview modal component for React Native.
4
4
  Think **Gorhom Bottom Sheet**, but for quick previews.
@@ -27,9 +27,9 @@ Perfect for:
27
27
  ## 📦 Installation
28
28
 
29
29
  ```bash
30
- npm install react-native-quicklook
30
+ npm install react-native-quick-preview
31
31
  # or
32
- yarn add react-native-quicklook
32
+ yarn add react-native-quick-preview
33
33
  ```
34
34
 
35
35
  ---
@@ -39,7 +39,7 @@ yarn add react-native-quicklook
39
39
  ```tsx
40
40
  import React, { useState } from 'react';
41
41
  import { View, Text, TouchableOpacity } from 'react-native';
42
- import { QuickLook } from 'react-native-quicklook';
42
+ import { QuickPreview } from 'react-native-quick-preview';
43
43
 
44
44
  export default function App() {
45
45
  const [visible, setVisible] = useState(false);
@@ -50,12 +50,12 @@ export default function App() {
50
50
  <Text>Show Quick Look</Text>
51
51
  </TouchableOpacity>
52
52
 
53
- <QuickLook visible={visible} onClose={() => setVisible(false)}>
53
+ <QuickPreview visible={visible} onClose={() => setVisible(false)}>
54
54
  <View style={{ backgroundColor: '#fff', padding: 20 }}>
55
55
  <Text style={{ fontSize: 18, fontWeight: 'bold' }}>Quick Preview Content</Text>
56
56
  <Text style={{ marginTop: 10 }}>Any custom content goes here.</Text>
57
57
  </View>
58
- </QuickLook>
58
+ </QuickPreview>
59
59
  </View>
60
60
  );
61
61
  }
@@ -67,33 +67,33 @@ export default function App() {
67
67
 
68
68
  ### 🛍️ E-commerce Product Quick View
69
69
  ```tsx
70
- <QuickLook visible={visible} onClose={onClose} onPressCard={onViewDetails}>
70
+ <QuickPreview visible={visible} onClose={onClose} onPressCard={onViewDetails}>
71
71
  <View>
72
72
  <Image source={{ uri: product.image }} style={{ width: '100%', height: 200 }} />
73
73
  <Text>{product.name}</Text>
74
74
  <Text>{product.price}</Text>
75
75
  </View>
76
- </QuickLook>
76
+ </QuickPreview>
77
77
  ```
78
78
 
79
79
  ### 📰 Article Preview
80
80
  ```tsx
81
- <QuickLook visible={visible} onClose={onClose} theme="dark">
81
+ <QuickPreview visible={visible} onClose={onClose} theme="dark">
82
82
  <View style={{ backgroundColor: '#1a1a1a' }}>
83
83
  <Image source={{ uri: article.coverImage }} style={{ width: '100%', height: 200 }} />
84
84
  <Text style={{ color: '#fff' }}>{article.title}</Text>
85
85
  <Text style={{ color: '#ccc' }}>{article.excerpt}</Text>
86
86
  </View>
87
- </QuickLook>
87
+ </QuickPreview>
88
88
  ```
89
89
 
90
90
  ### ✈️ Travel Destination Peek
91
91
  ```tsx
92
- <QuickLook visible={visible} onClose={onClose}>
92
+ <QuickPreview visible={visible} onClose={onClose}>
93
93
  <Image source={{ uri: destination.image }} style={{ width: '100%', height: 200 }} />
94
94
  <Text>{destination.title}</Text>
95
95
  <Text>From ${destination.price}</Text>
96
- </QuickLook>
96
+ </QuickPreview>
97
97
  ```
98
98
 
99
99
  ---
@@ -119,7 +119,7 @@ export default function App() {
119
119
  | `avoidKeyboard` | `boolean` | `false` | Avoid keyboard overlap |
120
120
  | `renderBackdrop` | `(opacity) => ReactNode` | `undefined` | Custom backdrop |
121
121
  | `onBackdropPress` | `() => void` | `undefined` | Backdrop press handler |
122
- | `testID` | `string` | `'quicklook'` | Test identifier |
122
+ | `testID` | `string` | `'quickpreview'` | Test identifier |
123
123
  | `accessibilityLabel` | `string` | `'Quick look'` | A11y label |
124
124
  | `stylesOverride` | `object` | `{}` | Override default styles |
125
125
 
@@ -129,7 +129,7 @@ export default function App() {
129
129
 
130
130
  ### Custom Backdrop
131
131
  ```tsx
132
- <QuickLook
132
+ <QuickPreview
133
133
  visible={visible}
134
134
  onClose={onClose}
135
135
  renderBackdrop={(opacity) => (
@@ -137,12 +137,12 @@ export default function App() {
137
137
  )}
138
138
  >
139
139
  {/* content */}
140
- </QuickLook>
140
+ </QuickPreview>
141
141
  ```
142
142
 
143
143
  ### Custom Styles
144
144
  ```tsx
145
- <QuickLook
145
+ <QuickPreview
146
146
  visible={visible}
147
147
  onClose={onClose}
148
148
  stylesOverride={{
@@ -151,7 +151,7 @@ export default function App() {
151
151
  }}
152
152
  >
153
153
  {/* content */}
154
- </QuickLook>
154
+ </QuickPreview>
155
155
  ```
156
156
 
157
157
  ---
@@ -161,12 +161,12 @@ export default function App() {
161
161
  ```tsx
162
162
  import { render, fireEvent } from '@testing-library/react-native';
163
163
 
164
- test('QuickLook closes on backdrop press', () => {
164
+ test('QuickPreview closes on backdrop press', () => {
165
165
  const onClose = jest.fn();
166
166
  const { getByTestId } = render(
167
- <QuickLook visible={true} onClose={onClose} testID="quicklook">
167
+ <QuickPreview visible={true} onClose={onClose} testID="quickpreview">
168
168
  <Text>Test content</Text>
169
- </QuickLook>
169
+ </QuickPreview>
170
170
  );
171
171
 
172
172
  fireEvent.press(getByTestId('ql-backdrop'));
@@ -185,4 +185,4 @@ test('QuickLook closes on backdrop press', () => {
185
185
 
186
186
  ## 📄 License
187
187
 
188
- MIT © Your Name
188
+ MIT © Oliver Lindblad
package/dist/index.d.mts CHANGED
@@ -3,14 +3,12 @@ import { Animated } from 'react-native';
3
3
 
4
4
  type ThemeMode = 'light' | 'dark';
5
5
  type CloseReason = 'programmatic' | 'backdrop' | 'backButton' | 'swipe';
6
- interface QuickLookProps {
6
+ interface QuickPreviewProps {
7
7
  visible: boolean;
8
8
  onClose: () => void;
9
9
  /** Lifecycle hooks (great for haptics/analytics) */
10
10
  onOpen?: () => void;
11
11
  onClosed?: (reason: CloseReason) => void;
12
- /** Optional: press whole card (prefer explicit CTAs as well) */
13
- onPressCard?: () => void;
14
12
  theme?: ThemeMode;
15
13
  backdropOpacity?: number;
16
14
  animationDuration?: number;
@@ -37,6 +35,6 @@ interface QuickLookProps {
37
35
  };
38
36
  }
39
37
 
40
- declare const QuickLook: React.FC<QuickLookProps>;
38
+ declare const QuickPreview: React.FC<QuickPreviewProps>;
41
39
 
42
- export { type CloseReason, QuickLook, type QuickLookProps, type ThemeMode };
40
+ export { type CloseReason, QuickPreview, type QuickPreviewProps, type ThemeMode };
package/dist/index.d.ts CHANGED
@@ -3,14 +3,12 @@ import { Animated } from 'react-native';
3
3
 
4
4
  type ThemeMode = 'light' | 'dark';
5
5
  type CloseReason = 'programmatic' | 'backdrop' | 'backButton' | 'swipe';
6
- interface QuickLookProps {
6
+ interface QuickPreviewProps {
7
7
  visible: boolean;
8
8
  onClose: () => void;
9
9
  /** Lifecycle hooks (great for haptics/analytics) */
10
10
  onOpen?: () => void;
11
11
  onClosed?: (reason: CloseReason) => void;
12
- /** Optional: press whole card (prefer explicit CTAs as well) */
13
- onPressCard?: () => void;
14
12
  theme?: ThemeMode;
15
13
  backdropOpacity?: number;
16
14
  animationDuration?: number;
@@ -37,6 +35,6 @@ interface QuickLookProps {
37
35
  };
38
36
  }
39
37
 
40
- declare const QuickLook: React.FC<QuickLookProps>;
38
+ declare const QuickPreview: React.FC<QuickPreviewProps>;
41
39
 
42
- export { type CloseReason, QuickLook, type QuickLookProps, type ThemeMode };
40
+ export { type CloseReason, QuickPreview, type QuickPreviewProps, type ThemeMode };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var react=require('react'),reactNative=require('react-native'),jsxRuntime=require('react/jsx-runtime');var K=Object.defineProperty,U=Object.defineProperties;var X=Object.getOwnPropertyDescriptors;var Q=Object.getOwnPropertySymbols;var Z=Object.prototype.hasOwnProperty,B=Object.prototype.propertyIsEnumerable;var x=(r,e,a)=>e in r?K(r,e,{enumerable:true,configurable:true,writable:true,value:a}):r[e]=a,I=(r,e)=>{for(var a in e||(e={}))Z.call(e,a)&&x(r,a,e[a]);if(Q)for(var a of Q(e))B.call(e,a)&&x(r,a,e[a]);return r},S=(r,e)=>U(r,X(e));var {width:ne,height:_}=reactNative.Dimensions.get("window"),oe="dialog",se=(r,e)=>`rgba(0,0,0,${e!=null?e:r==="dark"?.8:.5})`,ue=({visible:r,onClose:e,onOpen:a,onClosed:d,theme:g="light",backdropOpacity:w,animationDuration:f=220,closeOnBackdropPress:j=true,closeOnBackButton:z=true,enableSwipeToClose:m=true,swipeThreshold:R=80,unmountOnExit:M=true,avoidKeyboard:v=false,children:E,renderBackdrop:D,onBackdropPress:k,testID:T="quicklook",accessibilityLabel:Y="Quick look",stylesOverride:b={}})=>{let[u,L]=react.useState(false),[$,A]=react.useState(0),n=react.useRef(new reactNative.Animated.Value(0)).current,o=react.useRef(new reactNative.Animated.Value(.96)).current,s=react.useRef(new reactNative.Animated.Value(0)).current,G=react.useMemo(()=>se(g,w),[g,w]),l=react.useRef("programmatic");react.useEffect(()=>{r&&!u?(L(true),a==null||a(),requestAnimationFrame(()=>{reactNative.Animated.parallel([reactNative.Animated.timing(n,{toValue:1,duration:f,useNativeDriver:true}),reactNative.Animated.spring(o,{toValue:1,useNativeDriver:true,friction:7,tension:80})]).start();})):!r&&u&&reactNative.Animated.parallel([reactNative.Animated.timing(n,{toValue:0,duration:f,useNativeDriver:true}),reactNative.Animated.timing(o,{toValue:.96,duration:f,useNativeDriver:true})]).start(()=>{s.setValue(0),d==null||d(l.current),l.current="programmatic",M&&L(false);});},[r,u,f,n,o,s,M,a,d]),react.useEffect(()=>{if(!v)return;let y=reactNative.Keyboard.addListener("keyboardDidShow",p=>{var N,P;return A((P=(N=p.endCoordinates)==null?void 0:N.height)!=null?P:0)}),i=reactNative.Keyboard.addListener("keyboardDidHide",()=>A(0));return ()=>{y.remove(),i.remove();}},[v]);let J=react.useRef(reactNative.PanResponder.create({onMoveShouldSetPanResponder:(y,i)=>m&&Math.abs(i.dy)>Math.abs(i.dx)&&Math.abs(i.dy)>5,onPanResponderMove:(y,i)=>{if(m&&i.dy>0){s.setValue(i.dy);let p=Math.min(1,i.dy/(R*2));n.setValue(1-p*.25),o.setValue(1-p*.03);}},onPanResponderRelease:(y,i)=>{m&&(i.dy>R?(l.current="swipe",reactNative.Animated.parallel([reactNative.Animated.timing(s,{toValue:_*.35,duration:180,useNativeDriver:true}),reactNative.Animated.timing(n,{toValue:0,duration:180,useNativeDriver:true})]).start(()=>e==null?void 0:e())):reactNative.Animated.parallel([reactNative.Animated.spring(s,{toValue:0,useNativeDriver:true}),reactNative.Animated.spring(n,{toValue:1,useNativeDriver:true}),reactNative.Animated.spring(o,{toValue:1,useNativeDriver:true})]).start());}})).current;return !u&&!r?null:jsxRuntime.jsx(reactNative.Modal,{transparent:true,visible:u||r,animationType:"none",onRequestClose:()=>{z&&(l.current="backButton",e==null||e());},presentationStyle:"overFullScreen",statusBarTranslucent:reactNative.Platform.OS==="android",children:jsxRuntime.jsxs(reactNative.Animated.View,{style:[V.overlay,{backgroundColor:G,opacity:n},b.overlay],accessibilityViewIsModal:true,children:[D?D(n):jsxRuntime.jsx(reactNative.Pressable,{onPress:()=>{k==null||k(),j&&(l.current="backdrop",e==null||e());},style:reactNative.StyleSheet.absoluteFill,android_disableSound:true,accessibilityRole:"button",accessibilityLabel:"Close quick look",testID:"ql-backdrop"}),jsxRuntime.jsx(reactNative.View,{style:[V.centerWrap,{paddingBottom:Math.max(16,v?$:16)},b.centerWrap],pointerEvents:"box-none",children:jsxRuntime.jsx(reactNative.Animated.View,S(I({},m?J.panHandlers:{}),{style:[V.container,{transform:[{scale:o},{translateY:s}]},b.container],testID:T,accessibilityRole:oe,accessibilityViewIsModal:true,accessibilityLabel:Y,children:E}))})]})})},V=reactNative.StyleSheet.create({overlay:{flex:1,justifyContent:"center",alignItems:"center"},centerWrap:{flex:1,width:"100%",justifyContent:"center",alignItems:"center",paddingHorizontal:16},container:{width:Math.min(ne*.92,560),maxHeight:_*.82,borderRadius:16,overflow:"hidden",elevation:8,shadowColor:"#000",shadowOpacity:.2,shadowRadius:12,shadowOffset:{width:0,height:6},backgroundColor:"#fff"}});exports.QuickLook=ue;//# sourceMappingURL=index.js.map
1
+ 'use strict';var react=require('react'),reactNative=require('react-native'),jsxRuntime=require('react/jsx-runtime');var K=Object.defineProperty,U=Object.defineProperties;var X=Object.getOwnPropertyDescriptors;var x=Object.getOwnPropertySymbols;var Z=Object.prototype.hasOwnProperty,B=Object.prototype.propertyIsEnumerable;var I=(r,e,i)=>e in r?K(r,e,{enumerable:true,configurable:true,writable:true,value:i}):r[e]=i,S=(r,e)=>{for(var i in e||(e={}))Z.call(e,i)&&I(r,i,e[i]);if(x)for(var i of x(e))B.call(e,i)&&I(r,i,e[i]);return r},q=(r,e)=>U(r,X(e));var {width:ne,height:_}=reactNative.Dimensions.get("window"),se="dialog",ue=(r,e)=>`rgba(0,0,0,${e!=null?e:r==="dark"?.8:.5})`,oe=({visible:r,onClose:e,onOpen:i,onClosed:d,theme:g="light",backdropOpacity:R,animationDuration:f=220,closeOnBackdropPress:j=true,closeOnBackButton:z=true,enableSwipeToClose:v=true,swipeThreshold:M=80,unmountOnExit:k=true,avoidKeyboard:y=false,children:E,renderBackdrop:P,onBackdropPress:h,testID:T="quickpreview",accessibilityLabel:Y="Quick preview",stylesOverride:b={}})=>{let[o,D]=react.useState(false),[$,A]=react.useState(0),n=react.useRef(new reactNative.Animated.Value(0)).current,s=react.useRef(new reactNative.Animated.Value(.96)).current,u=react.useRef(new reactNative.Animated.Value(0)).current,G=react.useMemo(()=>ue(g,R),[g,R]),c=react.useRef("programmatic");react.useEffect(()=>{r&&!o?(D(true),i==null||i(),requestAnimationFrame(()=>{reactNative.Animated.parallel([reactNative.Animated.timing(n,{toValue:1,duration:f,useNativeDriver:true}),reactNative.Animated.spring(s,{toValue:1,useNativeDriver:true,friction:7,tension:80})]).start();})):!r&&o&&reactNative.Animated.parallel([reactNative.Animated.timing(n,{toValue:0,duration:f,useNativeDriver:true}),reactNative.Animated.timing(s,{toValue:.96,duration:f,useNativeDriver:true})]).start(()=>{u.setValue(0),d==null||d(c.current),c.current="programmatic",k&&D(false);});},[r,o,f,n,s,u,k,i,d]),react.useEffect(()=>{if(!y)return;let m=reactNative.Keyboard.addListener("keyboardDidShow",p=>{var N,Q;return A((Q=(N=p.endCoordinates)==null?void 0:N.height)!=null?Q:0)}),a=reactNative.Keyboard.addListener("keyboardDidHide",()=>A(0));return ()=>{m.remove(),a.remove();}},[y]);let J=react.useRef(reactNative.PanResponder.create({onMoveShouldSetPanResponder:(m,a)=>v&&Math.abs(a.dy)>Math.abs(a.dx)&&Math.abs(a.dy)>5,onPanResponderMove:(m,a)=>{if(v&&a.dy>0){u.setValue(a.dy);let p=Math.min(1,a.dy/(M*2));n.setValue(1-p*.25),s.setValue(1-p*.03);}},onPanResponderRelease:(m,a)=>{v&&(a.dy>M?(c.current="swipe",reactNative.Animated.parallel([reactNative.Animated.timing(u,{toValue:_*.35,duration:180,useNativeDriver:true}),reactNative.Animated.timing(n,{toValue:0,duration:180,useNativeDriver:true})]).start(()=>e==null?void 0:e())):reactNative.Animated.parallel([reactNative.Animated.spring(u,{toValue:0,useNativeDriver:true}),reactNative.Animated.spring(n,{toValue:1,useNativeDriver:true}),reactNative.Animated.spring(s,{toValue:1,useNativeDriver:true})]).start());}})).current;return !o&&!r?null:jsxRuntime.jsx(reactNative.Modal,{transparent:true,visible:o||r,animationType:"none",onRequestClose:()=>{z&&(c.current="backButton",e==null||e());},presentationStyle:"overFullScreen",statusBarTranslucent:reactNative.Platform.OS==="android",children:jsxRuntime.jsxs(reactNative.Animated.View,{style:[V.overlay,{backgroundColor:G,opacity:n},b.overlay],accessibilityViewIsModal:true,children:[P?P(n):jsxRuntime.jsx(reactNative.Pressable,{onPress:()=>{h==null||h(),j&&(c.current="backdrop",e==null||e());},style:reactNative.StyleSheet.absoluteFill,android_disableSound:true,accessibilityRole:"button",accessibilityLabel:"Close quick preview",testID:"qp-backdrop"}),jsxRuntime.jsx(reactNative.View,{style:[V.centerWrap,{paddingBottom:Math.max(16,y?$:16)},b.centerWrap],pointerEvents:"box-none",children:jsxRuntime.jsx(reactNative.Animated.View,q(S({},v?J.panHandlers:{}),{style:[V.container,{transform:[{scale:s},{translateY:u}]},b.container],testID:T,accessibilityRole:se,accessibilityViewIsModal:true,accessibilityLabel:Y,children:E}))})]})})},V=reactNative.StyleSheet.create({overlay:{flex:1,justifyContent:"center",alignItems:"center"},centerWrap:{flex:1,width:"100%",justifyContent:"center",alignItems:"center",paddingHorizontal:16},container:{width:Math.min(ne*.92,560),maxHeight:_*.82,borderRadius:16,overflow:"hidden",elevation:8,shadowColor:"#000",shadowOpacity:.2,shadowRadius:12,shadowOffset:{width:0,height:6},backgroundColor:"#fff"}});exports.QuickPreview=oe;//# sourceMappingURL=index.js.map
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/QuickLook.tsx"],"names":["screenWidth","screenHeight","Dimensions","dialogA11yRole","overlayColor","theme","custom","QuickLook","visible","onClose","onOpen","onClosed","backdropOpacity","animationDuration","closeOnBackdropPress","closeOnBackButton","enableSwipeToClose","swipeThreshold","unmountOnExit","avoidKeyboard","children","renderBackdrop","onBackdropPress","testID","accessibilityLabel","stylesOverride","mounted","setMounted","useState","kb","setKb","fade","useRef","Animated","scale","translateY","baseOverlay","useMemo","closeReasonRef","useEffect","show","Keyboard","e","_a","_b","hide","panResponder","PanResponder","_evt","g","jsx","Modal","Platform","jsxs","styles","Pressable","StyleSheet","View","__spreadProps","__spreadValues"],"mappings":"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","file":"index.js","sourcesContent":["// src/QuickLook.tsx\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport {\n View,\n StyleSheet,\n Modal,\n Dimensions,\n Animated,\n Platform,\n Pressable,\n PanResponder,\n Keyboard,\n} from 'react-native';\nimport type { AccessibilityRole } from 'react-native';\nimport type { CloseReason, QuickLookProps, ThemeMode } from './QuickLookProperties';\n\nconst { width: screenWidth, height: screenHeight } = Dimensions.get('window');\n\n// TS-safe across RN versions where \"dialog\" may not exist in AccessibilityRole\nconst dialogA11yRole = 'dialog' as unknown as AccessibilityRole;\n\nconst overlayColor = (theme: ThemeMode, custom?: number) =>\n `rgba(0,0,0,${custom ?? (theme === 'dark' ? 0.8 : 0.5)})`;\n\nexport const QuickLook: React.FC<QuickLookProps> = ({\n visible,\n onClose,\n onOpen,\n onClosed,\n theme = 'light',\n backdropOpacity,\n animationDuration = 220,\n closeOnBackdropPress = true,\n closeOnBackButton = true,\n enableSwipeToClose = true,\n swipeThreshold = 80,\n unmountOnExit = true,\n avoidKeyboard = false,\n children,\n renderBackdrop,\n onBackdropPress,\n testID = 'quicklook',\n accessibilityLabel = 'Quick look',\n stylesOverride = {},\n}) => {\n const [mounted, setMounted] = useState(false);\n const [kb, setKb] = useState(0); // keyboard height\n\n const fade = useRef(new Animated.Value(0)).current;\n const scale = useRef(new Animated.Value(0.96)).current;\n const translateY = useRef(new Animated.Value(0)).current;\n\n const baseOverlay = useMemo(() => overlayColor(theme, backdropOpacity), [theme, backdropOpacity]);\n\n // Track why we closed so we can report it to onClosed\n const closeReasonRef = useRef<CloseReason>('programmatic');\n\n // Mount/unmount with animation\n useEffect(() => {\n if (visible && !mounted) {\n setMounted(true);\n onOpen?.(); // great place to trigger optional haptics in-app\n\n requestAnimationFrame(() => {\n Animated.parallel([\n Animated.timing(fade, { toValue: 1, duration: animationDuration, useNativeDriver: true }),\n Animated.spring(scale, { toValue: 1, useNativeDriver: true, friction: 7, tension: 80 }),\n ]).start();\n });\n } else if (!visible && mounted) {\n Animated.parallel([\n Animated.timing(fade, { toValue: 0, duration: animationDuration, useNativeDriver: true }),\n Animated.timing(scale, { toValue: 0.96, duration: animationDuration, useNativeDriver: true }),\n ]).start(() => {\n translateY.setValue(0);\n onClosed?.(closeReasonRef.current);\n closeReasonRef.current = 'programmatic';\n if (unmountOnExit) setMounted(false);\n });\n }\n }, [visible, mounted, animationDuration, fade, scale, translateY, unmountOnExit, onOpen, onClosed]);\n\n // Keyboard avoidance (optional)\n useEffect(() => {\n if (!avoidKeyboard) return;\n const show = Keyboard.addListener('keyboardDidShow', (e) => setKb(e.endCoordinates?.height ?? 0));\n const hide = Keyboard.addListener('keyboardDidHide', () => setKb(0));\n return () => {\n show.remove();\n hide.remove();\n };\n }, [avoidKeyboard]);\n\n // Swipe to close\n const panResponder = useRef(\n PanResponder.create({\n onMoveShouldSetPanResponder: (_evt, g) =>\n enableSwipeToClose && Math.abs(g.dy) > Math.abs(g.dx) && Math.abs(g.dy) > 5,\n onPanResponderMove: (_evt, g) => {\n if (!enableSwipeToClose) return;\n if (g.dy > 0) {\n translateY.setValue(g.dy);\n const p = Math.min(1, g.dy / (swipeThreshold * 2));\n fade.setValue(1 - p * 0.25);\n scale.setValue(1 - p * 0.03);\n }\n },\n onPanResponderRelease: (_evt, g) => {\n if (!enableSwipeToClose) return;\n if (g.dy > swipeThreshold) {\n closeReasonRef.current = 'swipe';\n Animated.parallel([\n Animated.timing(translateY, { toValue: screenHeight * 0.35, duration: 180, useNativeDriver: true }),\n Animated.timing(fade, { toValue: 0, duration: 180, useNativeDriver: true }),\n ]).start(() => onClose?.());\n } else {\n Animated.parallel([\n Animated.spring(translateY, { toValue: 0, useNativeDriver: true }),\n Animated.spring(fade, { toValue: 1, useNativeDriver: true }),\n Animated.spring(scale, { toValue: 1, useNativeDriver: true }),\n ]).start();\n }\n },\n })\n ).current;\n\n if (!mounted && !visible) return null;\n\n return (\n <Modal\n transparent\n visible={mounted || visible}\n animationType=\"none\"\n onRequestClose={() => {\n if (closeOnBackButton) {\n closeReasonRef.current = 'backButton';\n onClose?.();\n }\n }}\n presentationStyle=\"overFullScreen\"\n statusBarTranslucent={Platform.OS === 'android'}\n >\n {/* Backdrop */}\n <Animated.View\n style={[\n styles.overlay,\n { backgroundColor: baseOverlay, opacity: fade },\n stylesOverride.overlay,\n ]}\n accessibilityViewIsModal\n >\n {renderBackdrop ? (\n // If you provide a custom backdrop, you control its hit area/closing\n renderBackdrop(fade as unknown as Animated.AnimatedInterpolation<number>)\n ) : (\n <Pressable\n onPress={() => {\n onBackdropPress?.();\n if (closeOnBackdropPress) {\n closeReasonRef.current = 'backdrop';\n onClose?.();\n }\n }}\n style={StyleSheet.absoluteFill}\n android_disableSound\n accessibilityRole=\"button\"\n accessibilityLabel=\"Close quick look\"\n testID=\"ql-backdrop\"\n />\n )}\n\n {/* Centered card */}\n <View\n style={[\n styles.centerWrap,\n { paddingBottom: Math.max(16, avoidKeyboard ? kb : 16) },\n stylesOverride.centerWrap,\n ]}\n pointerEvents=\"box-none\"\n >\n <Animated.View\n {...(enableSwipeToClose ? panResponder.panHandlers : {})}\n style={[\n styles.container,\n { transform: [{ scale }, { translateY }] },\n stylesOverride.container,\n ]}\n testID={testID}\n accessibilityRole={dialogA11yRole}\n accessibilityViewIsModal\n accessibilityLabel={accessibilityLabel}\n >\n {children}\n </Animated.View>\n </View>\n </Animated.View>\n </Modal>\n );\n};\n\nconst styles = StyleSheet.create({\n overlay: { flex: 1, justifyContent: 'center', alignItems: 'center' },\n centerWrap: {\n flex: 1,\n width: '100%',\n justifyContent: 'center',\n alignItems: 'center',\n paddingHorizontal: 16,\n },\n container: {\n width: Math.min(screenWidth * 0.92, 560),\n maxHeight: screenHeight * 0.82,\n borderRadius: 16,\n overflow: 'hidden',\n elevation: 8,\n shadowColor: '#000',\n shadowOpacity: 0.2,\n shadowRadius: 12,\n shadowOffset: { width: 0, height: 6 },\n backgroundColor: '#fff',\n },\n});\n"]}
1
+ {"version":3,"sources":["../src/QuickPreview.tsx"],"names":["screenWidth","screenHeight","Dimensions","dialogA11yRole","overlayColor","theme","custom","QuickPreview","visible","onClose","onOpen","onClosed","backdropOpacity","animationDuration","closeOnBackdropPress","closeOnBackButton","enableSwipeToClose","swipeThreshold","unmountOnExit","avoidKeyboard","children","renderBackdrop","onBackdropPress","testID","accessibilityLabel","stylesOverride","mounted","setMounted","useState","kb","setKb","fade","useRef","Animated","scale","translateY","baseOverlay","useMemo","closeReasonRef","useEffect","show","Keyboard","e","_a","_b","hide","panResponder","PanResponder","_evt","g","jsx","Modal","Platform","jsxs","styles","Pressable","StyleSheet","View","__spreadProps","__spreadValues"],"mappings":"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","file":"index.js","sourcesContent":["// src/QuickPreview.tsx\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport {\n View,\n StyleSheet,\n Modal,\n Dimensions,\n Animated,\n Platform,\n Pressable,\n PanResponder,\n Keyboard,\n} from 'react-native';\nimport type { AccessibilityRole } from 'react-native';\nimport type { CloseReason, QuickPreviewProps, ThemeMode } from './QuickPreviewProperties';\n\nconst { width: screenWidth, height: screenHeight } = Dimensions.get('window');\n\n// TS-safe across RN versions where \"dialog\" may not exist in AccessibilityRole\nconst dialogA11yRole = 'dialog' as unknown as AccessibilityRole;\n\nconst overlayColor = (theme: ThemeMode, custom?: number) =>\n `rgba(0,0,0,${custom ?? (theme === 'dark' ? 0.8 : 0.5)})`;\n\nexport const QuickPreview: React.FC<QuickPreviewProps> = ({\n visible,\n onClose,\n onOpen,\n onClosed,\n theme = 'light',\n backdropOpacity,\n animationDuration = 220,\n closeOnBackdropPress = true,\n closeOnBackButton = true,\n enableSwipeToClose = true,\n swipeThreshold = 80,\n unmountOnExit = true,\n avoidKeyboard = false,\n children,\n renderBackdrop,\n onBackdropPress,\n testID = 'quickpreview',\n accessibilityLabel = 'Quick preview',\n stylesOverride = {},\n}) => {\n const [mounted, setMounted] = useState(false);\n const [kb, setKb] = useState(0); // keyboard height\n\n const fade = useRef(new Animated.Value(0)).current;\n const scale = useRef(new Animated.Value(0.96)).current;\n const translateY = useRef(new Animated.Value(0)).current;\n\n const baseOverlay = useMemo(() => overlayColor(theme, backdropOpacity), [theme, backdropOpacity]);\n\n // Track why we closed so we can report it to onClosed\n const closeReasonRef = useRef<CloseReason>('programmatic');\n\n // Mount/unmount with animation\n useEffect(() => {\n if (visible && !mounted) {\n setMounted(true);\n onOpen?.(); // great place to trigger optional haptics in-app\n\n requestAnimationFrame(() => {\n Animated.parallel([\n Animated.timing(fade, { toValue: 1, duration: animationDuration, useNativeDriver: true }),\n Animated.spring(scale, { toValue: 1, useNativeDriver: true, friction: 7, tension: 80 }),\n ]).start();\n });\n } else if (!visible && mounted) {\n Animated.parallel([\n Animated.timing(fade, { toValue: 0, duration: animationDuration, useNativeDriver: true }),\n Animated.timing(scale, { toValue: 0.96, duration: animationDuration, useNativeDriver: true }),\n ]).start(() => {\n translateY.setValue(0);\n onClosed?.(closeReasonRef.current);\n closeReasonRef.current = 'programmatic';\n if (unmountOnExit) setMounted(false);\n });\n }\n }, [visible, mounted, animationDuration, fade, scale, translateY, unmountOnExit, onOpen, onClosed]);\n\n // Keyboard avoidance (optional)\n useEffect(() => {\n if (!avoidKeyboard) return;\n const show = Keyboard.addListener('keyboardDidShow', (e) => setKb(e.endCoordinates?.height ?? 0));\n const hide = Keyboard.addListener('keyboardDidHide', () => setKb(0));\n return () => {\n show.remove();\n hide.remove();\n };\n }, [avoidKeyboard]);\n\n // Swipe to close\n const panResponder = useRef(\n PanResponder.create({\n onMoveShouldSetPanResponder: (_evt, g) =>\n enableSwipeToClose && Math.abs(g.dy) > Math.abs(g.dx) && Math.abs(g.dy) > 5,\n onPanResponderMove: (_evt, g) => {\n if (!enableSwipeToClose) return;\n if (g.dy > 0) {\n translateY.setValue(g.dy);\n const p = Math.min(1, g.dy / (swipeThreshold * 2));\n fade.setValue(1 - p * 0.25);\n scale.setValue(1 - p * 0.03);\n }\n },\n onPanResponderRelease: (_evt, g) => {\n if (!enableSwipeToClose) return;\n if (g.dy > swipeThreshold) {\n closeReasonRef.current = 'swipe';\n Animated.parallel([\n Animated.timing(translateY, { toValue: screenHeight * 0.35, duration: 180, useNativeDriver: true }),\n Animated.timing(fade, { toValue: 0, duration: 180, useNativeDriver: true }),\n ]).start(() => onClose?.());\n } else {\n Animated.parallel([\n Animated.spring(translateY, { toValue: 0, useNativeDriver: true }),\n Animated.spring(fade, { toValue: 1, useNativeDriver: true }),\n Animated.spring(scale, { toValue: 1, useNativeDriver: true }),\n ]).start();\n }\n },\n })\n ).current;\n\n if (!mounted && !visible) return null;\n\n return (\n <Modal\n transparent\n visible={mounted || visible}\n animationType=\"none\"\n onRequestClose={() => {\n if (closeOnBackButton) {\n closeReasonRef.current = 'backButton';\n onClose?.();\n }\n }}\n presentationStyle=\"overFullScreen\"\n statusBarTranslucent={Platform.OS === 'android'}\n >\n {/* Backdrop */}\n <Animated.View\n style={[\n styles.overlay,\n { backgroundColor: baseOverlay, opacity: fade },\n stylesOverride.overlay,\n ]}\n accessibilityViewIsModal\n >\n {renderBackdrop ? (\n // If you provide a custom backdrop, you control its hit area/closing\n renderBackdrop(fade as unknown as Animated.AnimatedInterpolation<number>)\n ) : (\n <Pressable\n onPress={() => {\n onBackdropPress?.();\n if (closeOnBackdropPress) {\n closeReasonRef.current = 'backdrop';\n onClose?.();\n }\n }}\n style={StyleSheet.absoluteFill}\n android_disableSound\n accessibilityRole=\"button\"\n accessibilityLabel=\"Close quick preview\"\n testID=\"qp-backdrop\"\n />\n )}\n\n {/* Centered card */}\n <View\n style={[\n styles.centerWrap,\n { paddingBottom: Math.max(16, avoidKeyboard ? kb : 16) },\n stylesOverride.centerWrap,\n ]}\n pointerEvents=\"box-none\"\n >\n <Animated.View\n {...(enableSwipeToClose ? panResponder.panHandlers : {})}\n style={[\n styles.container,\n { transform: [{ scale }, { translateY }] },\n stylesOverride.container,\n ]}\n testID={testID}\n accessibilityRole={dialogA11yRole}\n accessibilityViewIsModal\n accessibilityLabel={accessibilityLabel}\n >\n {children}\n </Animated.View>\n </View>\n </Animated.View>\n </Modal>\n );\n};\n\nconst styles = StyleSheet.create({\n overlay: { flex: 1, justifyContent: 'center', alignItems: 'center' },\n centerWrap: {\n flex: 1,\n width: '100%',\n justifyContent: 'center',\n alignItems: 'center',\n paddingHorizontal: 16,\n },\n container: {\n width: Math.min(screenWidth * 0.92, 560),\n maxHeight: screenHeight * 0.82,\n borderRadius: 16,\n overflow: 'hidden',\n elevation: 8,\n shadowColor: '#000',\n shadowOpacity: 0.2,\n shadowRadius: 12,\n shadowOffset: { width: 0, height: 6 },\n backgroundColor: '#fff',\n },\n});\n"]}
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import {useState,useRef,useMemo,useEffect}from'react';import {Dimensions,StyleSheet,Animated,Keyboard,PanResponder,Modal,Pressable,View,Platform}from'react-native';import {jsx,jsxs}from'react/jsx-runtime';var K=Object.defineProperty,U=Object.defineProperties;var X=Object.getOwnPropertyDescriptors;var Q=Object.getOwnPropertySymbols;var Z=Object.prototype.hasOwnProperty,B=Object.prototype.propertyIsEnumerable;var x=(r,e,a)=>e in r?K(r,e,{enumerable:true,configurable:true,writable:true,value:a}):r[e]=a,I=(r,e)=>{for(var a in e||(e={}))Z.call(e,a)&&x(r,a,e[a]);if(Q)for(var a of Q(e))B.call(e,a)&&x(r,a,e[a]);return r},S=(r,e)=>U(r,X(e));var {width:ne,height:_}=Dimensions.get("window"),oe="dialog",se=(r,e)=>`rgba(0,0,0,${e!=null?e:r==="dark"?.8:.5})`,ue=({visible:r,onClose:e,onOpen:a,onClosed:d,theme:g="light",backdropOpacity:w,animationDuration:f=220,closeOnBackdropPress:j=true,closeOnBackButton:z=true,enableSwipeToClose:m=true,swipeThreshold:R=80,unmountOnExit:M=true,avoidKeyboard:v=false,children:E,renderBackdrop:D,onBackdropPress:k,testID:T="quicklook",accessibilityLabel:Y="Quick look",stylesOverride:b={}})=>{let[u,L]=useState(false),[$,A]=useState(0),n=useRef(new Animated.Value(0)).current,o=useRef(new Animated.Value(.96)).current,s=useRef(new Animated.Value(0)).current,G=useMemo(()=>se(g,w),[g,w]),l=useRef("programmatic");useEffect(()=>{r&&!u?(L(true),a==null||a(),requestAnimationFrame(()=>{Animated.parallel([Animated.timing(n,{toValue:1,duration:f,useNativeDriver:true}),Animated.spring(o,{toValue:1,useNativeDriver:true,friction:7,tension:80})]).start();})):!r&&u&&Animated.parallel([Animated.timing(n,{toValue:0,duration:f,useNativeDriver:true}),Animated.timing(o,{toValue:.96,duration:f,useNativeDriver:true})]).start(()=>{s.setValue(0),d==null||d(l.current),l.current="programmatic",M&&L(false);});},[r,u,f,n,o,s,M,a,d]),useEffect(()=>{if(!v)return;let y=Keyboard.addListener("keyboardDidShow",p=>{var N,P;return A((P=(N=p.endCoordinates)==null?void 0:N.height)!=null?P:0)}),i=Keyboard.addListener("keyboardDidHide",()=>A(0));return ()=>{y.remove(),i.remove();}},[v]);let J=useRef(PanResponder.create({onMoveShouldSetPanResponder:(y,i)=>m&&Math.abs(i.dy)>Math.abs(i.dx)&&Math.abs(i.dy)>5,onPanResponderMove:(y,i)=>{if(m&&i.dy>0){s.setValue(i.dy);let p=Math.min(1,i.dy/(R*2));n.setValue(1-p*.25),o.setValue(1-p*.03);}},onPanResponderRelease:(y,i)=>{m&&(i.dy>R?(l.current="swipe",Animated.parallel([Animated.timing(s,{toValue:_*.35,duration:180,useNativeDriver:true}),Animated.timing(n,{toValue:0,duration:180,useNativeDriver:true})]).start(()=>e==null?void 0:e())):Animated.parallel([Animated.spring(s,{toValue:0,useNativeDriver:true}),Animated.spring(n,{toValue:1,useNativeDriver:true}),Animated.spring(o,{toValue:1,useNativeDriver:true})]).start());}})).current;return !u&&!r?null:jsx(Modal,{transparent:true,visible:u||r,animationType:"none",onRequestClose:()=>{z&&(l.current="backButton",e==null||e());},presentationStyle:"overFullScreen",statusBarTranslucent:Platform.OS==="android",children:jsxs(Animated.View,{style:[V.overlay,{backgroundColor:G,opacity:n},b.overlay],accessibilityViewIsModal:true,children:[D?D(n):jsx(Pressable,{onPress:()=>{k==null||k(),j&&(l.current="backdrop",e==null||e());},style:StyleSheet.absoluteFill,android_disableSound:true,accessibilityRole:"button",accessibilityLabel:"Close quick look",testID:"ql-backdrop"}),jsx(View,{style:[V.centerWrap,{paddingBottom:Math.max(16,v?$:16)},b.centerWrap],pointerEvents:"box-none",children:jsx(Animated.View,S(I({},m?J.panHandlers:{}),{style:[V.container,{transform:[{scale:o},{translateY:s}]},b.container],testID:T,accessibilityRole:oe,accessibilityViewIsModal:true,accessibilityLabel:Y,children:E}))})]})})},V=StyleSheet.create({overlay:{flex:1,justifyContent:"center",alignItems:"center"},centerWrap:{flex:1,width:"100%",justifyContent:"center",alignItems:"center",paddingHorizontal:16},container:{width:Math.min(ne*.92,560),maxHeight:_*.82,borderRadius:16,overflow:"hidden",elevation:8,shadowColor:"#000",shadowOpacity:.2,shadowRadius:12,shadowOffset:{width:0,height:6},backgroundColor:"#fff"}});export{ue as QuickLook};//# sourceMappingURL=index.mjs.map
1
+ import {useState,useRef,useMemo,useEffect}from'react';import {Dimensions,StyleSheet,Animated,Keyboard,PanResponder,Modal,Pressable,View,Platform}from'react-native';import {jsx,jsxs}from'react/jsx-runtime';var K=Object.defineProperty,U=Object.defineProperties;var X=Object.getOwnPropertyDescriptors;var x=Object.getOwnPropertySymbols;var Z=Object.prototype.hasOwnProperty,B=Object.prototype.propertyIsEnumerable;var I=(r,e,i)=>e in r?K(r,e,{enumerable:true,configurable:true,writable:true,value:i}):r[e]=i,S=(r,e)=>{for(var i in e||(e={}))Z.call(e,i)&&I(r,i,e[i]);if(x)for(var i of x(e))B.call(e,i)&&I(r,i,e[i]);return r},q=(r,e)=>U(r,X(e));var {width:ne,height:_}=Dimensions.get("window"),se="dialog",ue=(r,e)=>`rgba(0,0,0,${e!=null?e:r==="dark"?.8:.5})`,oe=({visible:r,onClose:e,onOpen:i,onClosed:d,theme:g="light",backdropOpacity:R,animationDuration:f=220,closeOnBackdropPress:j=true,closeOnBackButton:z=true,enableSwipeToClose:v=true,swipeThreshold:M=80,unmountOnExit:k=true,avoidKeyboard:y=false,children:E,renderBackdrop:P,onBackdropPress:h,testID:T="quickpreview",accessibilityLabel:Y="Quick preview",stylesOverride:b={}})=>{let[o,D]=useState(false),[$,A]=useState(0),n=useRef(new Animated.Value(0)).current,s=useRef(new Animated.Value(.96)).current,u=useRef(new Animated.Value(0)).current,G=useMemo(()=>ue(g,R),[g,R]),c=useRef("programmatic");useEffect(()=>{r&&!o?(D(true),i==null||i(),requestAnimationFrame(()=>{Animated.parallel([Animated.timing(n,{toValue:1,duration:f,useNativeDriver:true}),Animated.spring(s,{toValue:1,useNativeDriver:true,friction:7,tension:80})]).start();})):!r&&o&&Animated.parallel([Animated.timing(n,{toValue:0,duration:f,useNativeDriver:true}),Animated.timing(s,{toValue:.96,duration:f,useNativeDriver:true})]).start(()=>{u.setValue(0),d==null||d(c.current),c.current="programmatic",k&&D(false);});},[r,o,f,n,s,u,k,i,d]),useEffect(()=>{if(!y)return;let m=Keyboard.addListener("keyboardDidShow",p=>{var N,Q;return A((Q=(N=p.endCoordinates)==null?void 0:N.height)!=null?Q:0)}),a=Keyboard.addListener("keyboardDidHide",()=>A(0));return ()=>{m.remove(),a.remove();}},[y]);let J=useRef(PanResponder.create({onMoveShouldSetPanResponder:(m,a)=>v&&Math.abs(a.dy)>Math.abs(a.dx)&&Math.abs(a.dy)>5,onPanResponderMove:(m,a)=>{if(v&&a.dy>0){u.setValue(a.dy);let p=Math.min(1,a.dy/(M*2));n.setValue(1-p*.25),s.setValue(1-p*.03);}},onPanResponderRelease:(m,a)=>{v&&(a.dy>M?(c.current="swipe",Animated.parallel([Animated.timing(u,{toValue:_*.35,duration:180,useNativeDriver:true}),Animated.timing(n,{toValue:0,duration:180,useNativeDriver:true})]).start(()=>e==null?void 0:e())):Animated.parallel([Animated.spring(u,{toValue:0,useNativeDriver:true}),Animated.spring(n,{toValue:1,useNativeDriver:true}),Animated.spring(s,{toValue:1,useNativeDriver:true})]).start());}})).current;return !o&&!r?null:jsx(Modal,{transparent:true,visible:o||r,animationType:"none",onRequestClose:()=>{z&&(c.current="backButton",e==null||e());},presentationStyle:"overFullScreen",statusBarTranslucent:Platform.OS==="android",children:jsxs(Animated.View,{style:[V.overlay,{backgroundColor:G,opacity:n},b.overlay],accessibilityViewIsModal:true,children:[P?P(n):jsx(Pressable,{onPress:()=>{h==null||h(),j&&(c.current="backdrop",e==null||e());},style:StyleSheet.absoluteFill,android_disableSound:true,accessibilityRole:"button",accessibilityLabel:"Close quick preview",testID:"qp-backdrop"}),jsx(View,{style:[V.centerWrap,{paddingBottom:Math.max(16,y?$:16)},b.centerWrap],pointerEvents:"box-none",children:jsx(Animated.View,q(S({},v?J.panHandlers:{}),{style:[V.container,{transform:[{scale:s},{translateY:u}]},b.container],testID:T,accessibilityRole:se,accessibilityViewIsModal:true,accessibilityLabel:Y,children:E}))})]})})},V=StyleSheet.create({overlay:{flex:1,justifyContent:"center",alignItems:"center"},centerWrap:{flex:1,width:"100%",justifyContent:"center",alignItems:"center",paddingHorizontal:16},container:{width:Math.min(ne*.92,560),maxHeight:_*.82,borderRadius:16,overflow:"hidden",elevation:8,shadowColor:"#000",shadowOpacity:.2,shadowRadius:12,shadowOffset:{width:0,height:6},backgroundColor:"#fff"}});export{oe as QuickPreview};//# sourceMappingURL=index.mjs.map
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/QuickLook.tsx"],"names":["screenWidth","screenHeight","Dimensions","dialogA11yRole","overlayColor","theme","custom","QuickLook","visible","onClose","onOpen","onClosed","backdropOpacity","animationDuration","closeOnBackdropPress","closeOnBackButton","enableSwipeToClose","swipeThreshold","unmountOnExit","avoidKeyboard","children","renderBackdrop","onBackdropPress","testID","accessibilityLabel","stylesOverride","mounted","setMounted","useState","kb","setKb","fade","useRef","Animated","scale","translateY","baseOverlay","useMemo","closeReasonRef","useEffect","show","Keyboard","e","_a","_b","hide","panResponder","PanResponder","_evt","g","jsx","Modal","Platform","jsxs","styles","Pressable","StyleSheet","View","__spreadProps","__spreadValues"],"mappings":"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","file":"index.mjs","sourcesContent":["// src/QuickLook.tsx\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport {\n View,\n StyleSheet,\n Modal,\n Dimensions,\n Animated,\n Platform,\n Pressable,\n PanResponder,\n Keyboard,\n} from 'react-native';\nimport type { AccessibilityRole } from 'react-native';\nimport type { CloseReason, QuickLookProps, ThemeMode } from './QuickLookProperties';\n\nconst { width: screenWidth, height: screenHeight } = Dimensions.get('window');\n\n// TS-safe across RN versions where \"dialog\" may not exist in AccessibilityRole\nconst dialogA11yRole = 'dialog' as unknown as AccessibilityRole;\n\nconst overlayColor = (theme: ThemeMode, custom?: number) =>\n `rgba(0,0,0,${custom ?? (theme === 'dark' ? 0.8 : 0.5)})`;\n\nexport const QuickLook: React.FC<QuickLookProps> = ({\n visible,\n onClose,\n onOpen,\n onClosed,\n theme = 'light',\n backdropOpacity,\n animationDuration = 220,\n closeOnBackdropPress = true,\n closeOnBackButton = true,\n enableSwipeToClose = true,\n swipeThreshold = 80,\n unmountOnExit = true,\n avoidKeyboard = false,\n children,\n renderBackdrop,\n onBackdropPress,\n testID = 'quicklook',\n accessibilityLabel = 'Quick look',\n stylesOverride = {},\n}) => {\n const [mounted, setMounted] = useState(false);\n const [kb, setKb] = useState(0); // keyboard height\n\n const fade = useRef(new Animated.Value(0)).current;\n const scale = useRef(new Animated.Value(0.96)).current;\n const translateY = useRef(new Animated.Value(0)).current;\n\n const baseOverlay = useMemo(() => overlayColor(theme, backdropOpacity), [theme, backdropOpacity]);\n\n // Track why we closed so we can report it to onClosed\n const closeReasonRef = useRef<CloseReason>('programmatic');\n\n // Mount/unmount with animation\n useEffect(() => {\n if (visible && !mounted) {\n setMounted(true);\n onOpen?.(); // great place to trigger optional haptics in-app\n\n requestAnimationFrame(() => {\n Animated.parallel([\n Animated.timing(fade, { toValue: 1, duration: animationDuration, useNativeDriver: true }),\n Animated.spring(scale, { toValue: 1, useNativeDriver: true, friction: 7, tension: 80 }),\n ]).start();\n });\n } else if (!visible && mounted) {\n Animated.parallel([\n Animated.timing(fade, { toValue: 0, duration: animationDuration, useNativeDriver: true }),\n Animated.timing(scale, { toValue: 0.96, duration: animationDuration, useNativeDriver: true }),\n ]).start(() => {\n translateY.setValue(0);\n onClosed?.(closeReasonRef.current);\n closeReasonRef.current = 'programmatic';\n if (unmountOnExit) setMounted(false);\n });\n }\n }, [visible, mounted, animationDuration, fade, scale, translateY, unmountOnExit, onOpen, onClosed]);\n\n // Keyboard avoidance (optional)\n useEffect(() => {\n if (!avoidKeyboard) return;\n const show = Keyboard.addListener('keyboardDidShow', (e) => setKb(e.endCoordinates?.height ?? 0));\n const hide = Keyboard.addListener('keyboardDidHide', () => setKb(0));\n return () => {\n show.remove();\n hide.remove();\n };\n }, [avoidKeyboard]);\n\n // Swipe to close\n const panResponder = useRef(\n PanResponder.create({\n onMoveShouldSetPanResponder: (_evt, g) =>\n enableSwipeToClose && Math.abs(g.dy) > Math.abs(g.dx) && Math.abs(g.dy) > 5,\n onPanResponderMove: (_evt, g) => {\n if (!enableSwipeToClose) return;\n if (g.dy > 0) {\n translateY.setValue(g.dy);\n const p = Math.min(1, g.dy / (swipeThreshold * 2));\n fade.setValue(1 - p * 0.25);\n scale.setValue(1 - p * 0.03);\n }\n },\n onPanResponderRelease: (_evt, g) => {\n if (!enableSwipeToClose) return;\n if (g.dy > swipeThreshold) {\n closeReasonRef.current = 'swipe';\n Animated.parallel([\n Animated.timing(translateY, { toValue: screenHeight * 0.35, duration: 180, useNativeDriver: true }),\n Animated.timing(fade, { toValue: 0, duration: 180, useNativeDriver: true }),\n ]).start(() => onClose?.());\n } else {\n Animated.parallel([\n Animated.spring(translateY, { toValue: 0, useNativeDriver: true }),\n Animated.spring(fade, { toValue: 1, useNativeDriver: true }),\n Animated.spring(scale, { toValue: 1, useNativeDriver: true }),\n ]).start();\n }\n },\n })\n ).current;\n\n if (!mounted && !visible) return null;\n\n return (\n <Modal\n transparent\n visible={mounted || visible}\n animationType=\"none\"\n onRequestClose={() => {\n if (closeOnBackButton) {\n closeReasonRef.current = 'backButton';\n onClose?.();\n }\n }}\n presentationStyle=\"overFullScreen\"\n statusBarTranslucent={Platform.OS === 'android'}\n >\n {/* Backdrop */}\n <Animated.View\n style={[\n styles.overlay,\n { backgroundColor: baseOverlay, opacity: fade },\n stylesOverride.overlay,\n ]}\n accessibilityViewIsModal\n >\n {renderBackdrop ? (\n // If you provide a custom backdrop, you control its hit area/closing\n renderBackdrop(fade as unknown as Animated.AnimatedInterpolation<number>)\n ) : (\n <Pressable\n onPress={() => {\n onBackdropPress?.();\n if (closeOnBackdropPress) {\n closeReasonRef.current = 'backdrop';\n onClose?.();\n }\n }}\n style={StyleSheet.absoluteFill}\n android_disableSound\n accessibilityRole=\"button\"\n accessibilityLabel=\"Close quick look\"\n testID=\"ql-backdrop\"\n />\n )}\n\n {/* Centered card */}\n <View\n style={[\n styles.centerWrap,\n { paddingBottom: Math.max(16, avoidKeyboard ? kb : 16) },\n stylesOverride.centerWrap,\n ]}\n pointerEvents=\"box-none\"\n >\n <Animated.View\n {...(enableSwipeToClose ? panResponder.panHandlers : {})}\n style={[\n styles.container,\n { transform: [{ scale }, { translateY }] },\n stylesOverride.container,\n ]}\n testID={testID}\n accessibilityRole={dialogA11yRole}\n accessibilityViewIsModal\n accessibilityLabel={accessibilityLabel}\n >\n {children}\n </Animated.View>\n </View>\n </Animated.View>\n </Modal>\n );\n};\n\nconst styles = StyleSheet.create({\n overlay: { flex: 1, justifyContent: 'center', alignItems: 'center' },\n centerWrap: {\n flex: 1,\n width: '100%',\n justifyContent: 'center',\n alignItems: 'center',\n paddingHorizontal: 16,\n },\n container: {\n width: Math.min(screenWidth * 0.92, 560),\n maxHeight: screenHeight * 0.82,\n borderRadius: 16,\n overflow: 'hidden',\n elevation: 8,\n shadowColor: '#000',\n shadowOpacity: 0.2,\n shadowRadius: 12,\n shadowOffset: { width: 0, height: 6 },\n backgroundColor: '#fff',\n },\n});\n"]}
1
+ {"version":3,"sources":["../src/QuickPreview.tsx"],"names":["screenWidth","screenHeight","Dimensions","dialogA11yRole","overlayColor","theme","custom","QuickPreview","visible","onClose","onOpen","onClosed","backdropOpacity","animationDuration","closeOnBackdropPress","closeOnBackButton","enableSwipeToClose","swipeThreshold","unmountOnExit","avoidKeyboard","children","renderBackdrop","onBackdropPress","testID","accessibilityLabel","stylesOverride","mounted","setMounted","useState","kb","setKb","fade","useRef","Animated","scale","translateY","baseOverlay","useMemo","closeReasonRef","useEffect","show","Keyboard","e","_a","_b","hide","panResponder","PanResponder","_evt","g","jsx","Modal","Platform","jsxs","styles","Pressable","StyleSheet","View","__spreadProps","__spreadValues"],"mappings":"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","file":"index.mjs","sourcesContent":["// src/QuickPreview.tsx\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport {\n View,\n StyleSheet,\n Modal,\n Dimensions,\n Animated,\n Platform,\n Pressable,\n PanResponder,\n Keyboard,\n} from 'react-native';\nimport type { AccessibilityRole } from 'react-native';\nimport type { CloseReason, QuickPreviewProps, ThemeMode } from './QuickPreviewProperties';\n\nconst { width: screenWidth, height: screenHeight } = Dimensions.get('window');\n\n// TS-safe across RN versions where \"dialog\" may not exist in AccessibilityRole\nconst dialogA11yRole = 'dialog' as unknown as AccessibilityRole;\n\nconst overlayColor = (theme: ThemeMode, custom?: number) =>\n `rgba(0,0,0,${custom ?? (theme === 'dark' ? 0.8 : 0.5)})`;\n\nexport const QuickPreview: React.FC<QuickPreviewProps> = ({\n visible,\n onClose,\n onOpen,\n onClosed,\n theme = 'light',\n backdropOpacity,\n animationDuration = 220,\n closeOnBackdropPress = true,\n closeOnBackButton = true,\n enableSwipeToClose = true,\n swipeThreshold = 80,\n unmountOnExit = true,\n avoidKeyboard = false,\n children,\n renderBackdrop,\n onBackdropPress,\n testID = 'quickpreview',\n accessibilityLabel = 'Quick preview',\n stylesOverride = {},\n}) => {\n const [mounted, setMounted] = useState(false);\n const [kb, setKb] = useState(0); // keyboard height\n\n const fade = useRef(new Animated.Value(0)).current;\n const scale = useRef(new Animated.Value(0.96)).current;\n const translateY = useRef(new Animated.Value(0)).current;\n\n const baseOverlay = useMemo(() => overlayColor(theme, backdropOpacity), [theme, backdropOpacity]);\n\n // Track why we closed so we can report it to onClosed\n const closeReasonRef = useRef<CloseReason>('programmatic');\n\n // Mount/unmount with animation\n useEffect(() => {\n if (visible && !mounted) {\n setMounted(true);\n onOpen?.(); // great place to trigger optional haptics in-app\n\n requestAnimationFrame(() => {\n Animated.parallel([\n Animated.timing(fade, { toValue: 1, duration: animationDuration, useNativeDriver: true }),\n Animated.spring(scale, { toValue: 1, useNativeDriver: true, friction: 7, tension: 80 }),\n ]).start();\n });\n } else if (!visible && mounted) {\n Animated.parallel([\n Animated.timing(fade, { toValue: 0, duration: animationDuration, useNativeDriver: true }),\n Animated.timing(scale, { toValue: 0.96, duration: animationDuration, useNativeDriver: true }),\n ]).start(() => {\n translateY.setValue(0);\n onClosed?.(closeReasonRef.current);\n closeReasonRef.current = 'programmatic';\n if (unmountOnExit) setMounted(false);\n });\n }\n }, [visible, mounted, animationDuration, fade, scale, translateY, unmountOnExit, onOpen, onClosed]);\n\n // Keyboard avoidance (optional)\n useEffect(() => {\n if (!avoidKeyboard) return;\n const show = Keyboard.addListener('keyboardDidShow', (e) => setKb(e.endCoordinates?.height ?? 0));\n const hide = Keyboard.addListener('keyboardDidHide', () => setKb(0));\n return () => {\n show.remove();\n hide.remove();\n };\n }, [avoidKeyboard]);\n\n // Swipe to close\n const panResponder = useRef(\n PanResponder.create({\n onMoveShouldSetPanResponder: (_evt, g) =>\n enableSwipeToClose && Math.abs(g.dy) > Math.abs(g.dx) && Math.abs(g.dy) > 5,\n onPanResponderMove: (_evt, g) => {\n if (!enableSwipeToClose) return;\n if (g.dy > 0) {\n translateY.setValue(g.dy);\n const p = Math.min(1, g.dy / (swipeThreshold * 2));\n fade.setValue(1 - p * 0.25);\n scale.setValue(1 - p * 0.03);\n }\n },\n onPanResponderRelease: (_evt, g) => {\n if (!enableSwipeToClose) return;\n if (g.dy > swipeThreshold) {\n closeReasonRef.current = 'swipe';\n Animated.parallel([\n Animated.timing(translateY, { toValue: screenHeight * 0.35, duration: 180, useNativeDriver: true }),\n Animated.timing(fade, { toValue: 0, duration: 180, useNativeDriver: true }),\n ]).start(() => onClose?.());\n } else {\n Animated.parallel([\n Animated.spring(translateY, { toValue: 0, useNativeDriver: true }),\n Animated.spring(fade, { toValue: 1, useNativeDriver: true }),\n Animated.spring(scale, { toValue: 1, useNativeDriver: true }),\n ]).start();\n }\n },\n })\n ).current;\n\n if (!mounted && !visible) return null;\n\n return (\n <Modal\n transparent\n visible={mounted || visible}\n animationType=\"none\"\n onRequestClose={() => {\n if (closeOnBackButton) {\n closeReasonRef.current = 'backButton';\n onClose?.();\n }\n }}\n presentationStyle=\"overFullScreen\"\n statusBarTranslucent={Platform.OS === 'android'}\n >\n {/* Backdrop */}\n <Animated.View\n style={[\n styles.overlay,\n { backgroundColor: baseOverlay, opacity: fade },\n stylesOverride.overlay,\n ]}\n accessibilityViewIsModal\n >\n {renderBackdrop ? (\n // If you provide a custom backdrop, you control its hit area/closing\n renderBackdrop(fade as unknown as Animated.AnimatedInterpolation<number>)\n ) : (\n <Pressable\n onPress={() => {\n onBackdropPress?.();\n if (closeOnBackdropPress) {\n closeReasonRef.current = 'backdrop';\n onClose?.();\n }\n }}\n style={StyleSheet.absoluteFill}\n android_disableSound\n accessibilityRole=\"button\"\n accessibilityLabel=\"Close quick preview\"\n testID=\"qp-backdrop\"\n />\n )}\n\n {/* Centered card */}\n <View\n style={[\n styles.centerWrap,\n { paddingBottom: Math.max(16, avoidKeyboard ? kb : 16) },\n stylesOverride.centerWrap,\n ]}\n pointerEvents=\"box-none\"\n >\n <Animated.View\n {...(enableSwipeToClose ? panResponder.panHandlers : {})}\n style={[\n styles.container,\n { transform: [{ scale }, { translateY }] },\n stylesOverride.container,\n ]}\n testID={testID}\n accessibilityRole={dialogA11yRole}\n accessibilityViewIsModal\n accessibilityLabel={accessibilityLabel}\n >\n {children}\n </Animated.View>\n </View>\n </Animated.View>\n </Modal>\n );\n};\n\nconst styles = StyleSheet.create({\n overlay: { flex: 1, justifyContent: 'center', alignItems: 'center' },\n centerWrap: {\n flex: 1,\n width: '100%',\n justifyContent: 'center',\n alignItems: 'center',\n paddingHorizontal: 16,\n },\n container: {\n width: Math.min(screenWidth * 0.92, 560),\n maxHeight: screenHeight * 0.82,\n borderRadius: 16,\n overflow: 'hidden',\n elevation: 8,\n shadowColor: '#000',\n shadowOpacity: 0.2,\n shadowRadius: 12,\n shadowOffset: { width: 0, height: 6 },\n backgroundColor: '#fff',\n },\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-quick-preview",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "A beautiful, customizable quick preview modal component for React Native",
5
5
  "author": "Oliver Lindblad",
6
6
  "license": "MIT",
@@ -37,7 +37,24 @@
37
37
  "react-native",
38
38
  "modal",
39
39
  "preview",
40
- "quicklook",
40
+ "quickpreview",
41
+ "quick-preview",
42
+ "quick-view",
43
+ "quick-view-modal",
44
+ "quick-view-dialog",
45
+ "quick-view-sheet",
46
+ "quick-view-popover",
47
+ "quick-view-drawer",
48
+ "quick-view-modal",
49
+ "quick-view-dialog",
50
+ "quick-view-sheet",
51
+ "quick-view-popover",
52
+ "quick-view-drawer",
53
+ "quick-view-modal",
54
+ "quick-view-dialog",
55
+ "quick-view-sheet",
56
+ "quick-view-popover",
57
+ "quick-view-drawer",
41
58
  "expo",
42
59
  "typescript",
43
60
  "ui",
@@ -70,12 +87,12 @@
70
87
 
71
88
  "repository": {
72
89
  "type": "git",
73
- "url": "https://github.com/Hashtagsmile/react-native-quicklook.git"
90
+ "url": "https://github.com/Hashtagsmile/react-native-quick-preview.git"
74
91
  },
75
92
  "bugs": {
76
- "url": "https://github.com/Hashtagsmile/react-native-quicklook/issues"
93
+ "url": "https://github.com/Hashtagsmile/react-native-quick-preview/issues"
77
94
  },
78
- "homepage": "https://github.com/Hashtagsmile/react-native-quicklook#readme",
95
+ "homepage": "https://github.com/Hashtagsmile/react-native-quick-preview#readme",
79
96
  "publishConfig": { "access": "public" },
80
97
  "engines": { "node": ">=16" }
81
98
  }
@@ -1,4 +1,4 @@
1
- // src/QuickLook.tsx
1
+ // src/QuickPreview.tsx
2
2
  import React, { useEffect, useMemo, useRef, useState } from 'react';
3
3
  import {
4
4
  View,
@@ -12,7 +12,7 @@ import {
12
12
  Keyboard,
13
13
  } from 'react-native';
14
14
  import type { AccessibilityRole } from 'react-native';
15
- import type { CloseReason, QuickLookProps, ThemeMode } from './QuickLookProperties';
15
+ import type { CloseReason, QuickPreviewProps, ThemeMode } from './QuickPreviewProperties';
16
16
 
17
17
  const { width: screenWidth, height: screenHeight } = Dimensions.get('window');
18
18
 
@@ -22,7 +22,7 @@ const dialogA11yRole = 'dialog' as unknown as AccessibilityRole;
22
22
  const overlayColor = (theme: ThemeMode, custom?: number) =>
23
23
  `rgba(0,0,0,${custom ?? (theme === 'dark' ? 0.8 : 0.5)})`;
24
24
 
25
- export const QuickLook: React.FC<QuickLookProps> = ({
25
+ export const QuickPreview: React.FC<QuickPreviewProps> = ({
26
26
  visible,
27
27
  onClose,
28
28
  onOpen,
@@ -39,8 +39,8 @@ export const QuickLook: React.FC<QuickLookProps> = ({
39
39
  children,
40
40
  renderBackdrop,
41
41
  onBackdropPress,
42
- testID = 'quicklook',
43
- accessibilityLabel = 'Quick look',
42
+ testID = 'quickpreview',
43
+ accessibilityLabel = 'Quick preview',
44
44
  stylesOverride = {},
45
45
  }) => {
46
46
  const [mounted, setMounted] = useState(false);
@@ -164,8 +164,8 @@ export const QuickLook: React.FC<QuickLookProps> = ({
164
164
  style={StyleSheet.absoluteFill}
165
165
  android_disableSound
166
166
  accessibilityRole="button"
167
- accessibilityLabel="Close quick look"
168
- testID="ql-backdrop"
167
+ accessibilityLabel="Close quick preview"
168
+ testID="qp-backdrop"
169
169
  />
170
170
  )}
171
171
 
@@ -5,7 +5,7 @@ export type ThemeMode = 'light' | 'dark';
5
5
  export type CloseReason = 'programmatic' | 'backdrop' | 'backButton' | 'swipe';
6
6
 
7
7
 
8
- export interface QuickLookProps {
8
+ export interface QuickPreviewProps {
9
9
  visible: boolean;
10
10
  onClose: () => void;
11
11
 
@@ -13,8 +13,6 @@ export interface QuickLookProps {
13
13
  onOpen?: () => void; // fires when animating in
14
14
  onClosed?: (reason: CloseReason) => void; // fires after fully closed
15
15
 
16
- /** Optional: press whole card (prefer explicit CTAs as well) */
17
- onPressCard?: () => void;
18
16
 
19
17
  theme?: ThemeMode;
20
18
  backdropOpacity?: number; // default 0.5 light / 0.8 dark
package/src/index.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { QuickLook } from './QuickLook';
2
- export type { QuickLookProps, ThemeMode, CloseReason } from './QuickLookProperties';
1
+ export { QuickPreview } from './QuickPreview';
2
+ export type { QuickPreviewProps, ThemeMode, CloseReason } from './QuickPreviewProperties';