react-native-quick-preview 1.0.4 → 2.0.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.
package/dist/index.js CHANGED
@@ -1,2 +1,420 @@
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';
2
+
3
+ var React5 = require('react');
4
+ var reactNative = require('react-native');
5
+ var reactNativePortalize = require('react-native-portalize');
6
+ var Animated = require('react-native-reanimated');
7
+ var reactNativeSafeAreaContext = require('react-native-safe-area-context');
8
+ var jsxRuntime = require('react/jsx-runtime');
9
+ var reactNativeGestureHandler = require('react-native-gesture-handler');
10
+
11
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
12
+
13
+ var React5__default = /*#__PURE__*/_interopDefault(React5);
14
+ var Animated__default = /*#__PURE__*/_interopDefault(Animated);
15
+
16
+ var __defProp = Object.defineProperty;
17
+ var __defProps = Object.defineProperties;
18
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
19
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
20
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
21
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
22
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
23
+ var __spreadValues = (a, b) => {
24
+ for (var prop in b || (b = {}))
25
+ if (__hasOwnProp.call(b, prop))
26
+ __defNormalProp(a, prop, b[prop]);
27
+ if (__getOwnPropSymbols)
28
+ for (var prop of __getOwnPropSymbols(b)) {
29
+ if (__propIsEnum.call(b, prop))
30
+ __defNormalProp(a, prop, b[prop]);
31
+ }
32
+ return a;
33
+ };
34
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
35
+ var __objRest = (source, exclude) => {
36
+ var target = {};
37
+ for (var prop in source)
38
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
39
+ target[prop] = source[prop];
40
+ if (source != null && __getOwnPropSymbols)
41
+ for (var prop of __getOwnPropSymbols(source)) {
42
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
43
+ target[prop] = source[prop];
44
+ }
45
+ return target;
46
+ };
47
+ function Backdrop({
48
+ onPress,
49
+ dismissOnBackdropPress = true
50
+ }) {
51
+ const opacity = Animated.useSharedValue(0);
52
+ React5__default.default.useEffect(() => {
53
+ opacity.value = Animated.withTiming(1, { duration: 160 });
54
+ return () => {
55
+ opacity.value = 0;
56
+ };
57
+ }, [opacity]);
58
+ const style = Animated.useAnimatedStyle(() => __spreadProps(__spreadValues({
59
+ backgroundColor: "rgba(0,0,0,0.5)"
60
+ }, reactNative.StyleSheet.absoluteFillObject), {
61
+ opacity: opacity.value
62
+ }));
63
+ return /* @__PURE__ */ jsxRuntime.jsx(Animated__default.default.View, { style, pointerEvents: dismissOnBackdropPress && onPress ? "auto" : "none", children: dismissOnBackdropPress && onPress ? /* @__PURE__ */ jsxRuntime.jsx(
64
+ reactNative.Pressable,
65
+ {
66
+ style: reactNative.StyleSheet.absoluteFill,
67
+ onPress,
68
+ accessibilityRole: "button",
69
+ accessibilityLabel: "Close preview"
70
+ }
71
+ ) : null });
72
+ }
73
+
74
+ // src/internal/resolveSize.ts
75
+ function resolveSizeStyle(size) {
76
+ if (size == null || size === "auto") return {};
77
+ if (typeof size === "number") return { maxHeight: size };
78
+ const out = {};
79
+ if (typeof size.maxHeight === "number") out.maxHeight = size.maxHeight;
80
+ if (typeof size.maxWidth === "number") out.maxWidth = size.maxWidth;
81
+ return out;
82
+ }
83
+ function SheetContainer({
84
+ children,
85
+ options,
86
+ insets,
87
+ onRequestClose
88
+ }) {
89
+ var _a2, _b;
90
+ const translateY = Animated.useSharedValue(1e3);
91
+ const dismissOnPanDown = (_a2 = options == null ? void 0 : options.dismissOnPanDown) != null ? _a2 : true;
92
+ React5__default.default.useEffect(() => {
93
+ translateY.value = Animated.withTiming(0, { duration: 300, easing: Animated.Easing.out(Animated.Easing.cubic) });
94
+ }, [translateY]);
95
+ const pan = reactNativeGestureHandler.Gesture.Pan().onUpdate((e) => {
96
+ if (!dismissOnPanDown) return;
97
+ translateY.value = Math.max(0, e.translationY);
98
+ }).onEnd((e) => {
99
+ const shouldClose = e.velocityY > 1e3 || translateY.value > 140;
100
+ if (shouldClose) {
101
+ translateY.value = Animated.withTiming(800, { duration: 200 }, (finished) => {
102
+ if (finished) Animated.runOnJS(onRequestClose)();
103
+ });
104
+ } else {
105
+ translateY.value = Animated.withTiming(0, { duration: 240, easing: Animated.Easing.out(Animated.Easing.cubic) });
106
+ }
107
+ });
108
+ const style = Animated.useAnimatedStyle(() => ({
109
+ transform: [{ translateY: translateY.value }]
110
+ }));
111
+ const sizeStyle = resolveSizeStyle(options == null ? void 0 : options.size);
112
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNativeGestureHandler.GestureDetector, { gesture: pan, children: /* @__PURE__ */ jsxRuntime.jsxs(
113
+ Animated__default.default.View,
114
+ {
115
+ style: [styles.sheet, sizeStyle, style, { paddingBottom: Math.max(insets.bottom, 12) }],
116
+ accessibilityRole: options == null ? void 0 : options.accessibilityRole,
117
+ accessibilityLabel: (_b = options == null ? void 0 : options.accessibilityLabel) != null ? _b : "Quick preview",
118
+ children: [
119
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.grabber }),
120
+ children
121
+ ]
122
+ }
123
+ ) });
124
+ }
125
+ var styles = reactNative.StyleSheet.create({
126
+ sheet: {
127
+ position: "absolute",
128
+ left: 0,
129
+ right: 0,
130
+ bottom: 0,
131
+ borderTopLeftRadius: 16,
132
+ borderTopRightRadius: 16,
133
+ paddingTop: 8,
134
+ backgroundColor: "white",
135
+ overflow: "hidden",
136
+ elevation: 3
137
+ },
138
+ grabber: {
139
+ alignSelf: "center",
140
+ width: 40,
141
+ height: 4,
142
+ borderRadius: 2,
143
+ backgroundColor: "rgba(0,0,0,0.2)",
144
+ marginBottom: 8
145
+ }
146
+ });
147
+ function PopoverContainer({
148
+ children,
149
+ options,
150
+ insets: _insets,
151
+ onRequestClose: _onRequestClose
152
+ // kept for API parity with SheetContainer
153
+ }) {
154
+ var _a2;
155
+ const scale = Animated.useSharedValue(0.96);
156
+ const opacity = Animated.useSharedValue(0);
157
+ React5__default.default.useEffect(() => {
158
+ scale.value = Animated.withTiming(1, { duration: 200, easing: Animated.Easing.out(Animated.Easing.cubic) });
159
+ opacity.value = Animated.withTiming(1, { duration: 160, easing: Animated.Easing.out(Animated.Easing.quad) });
160
+ }, [scale, opacity]);
161
+ const container = Animated.useAnimatedStyle(() => ({
162
+ opacity: opacity.value,
163
+ transform: [{ scale: scale.value }]
164
+ }));
165
+ const sizeStyle = resolveSizeStyle(options == null ? void 0 : options.size);
166
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [reactNative.StyleSheet.absoluteFill, styles2.center], pointerEvents: "box-none", children: /* @__PURE__ */ jsxRuntime.jsx(
167
+ Animated__default.default.View,
168
+ {
169
+ style: [styles2.card, sizeStyle, container],
170
+ accessibilityRole: options == null ? void 0 : options.accessibilityRole,
171
+ accessibilityLabel: (_a2 = options == null ? void 0 : options.accessibilityLabel) != null ? _a2 : "Quick preview",
172
+ children
173
+ }
174
+ ) });
175
+ }
176
+ var styles2 = reactNative.StyleSheet.create({
177
+ center: { justifyContent: "center", alignItems: "center" },
178
+ card: {
179
+ maxWidth: 520,
180
+ width: "92%",
181
+ maxHeight: "86%",
182
+ borderRadius: 16,
183
+ backgroundColor: "white",
184
+ overflow: "hidden",
185
+ elevation: 3
186
+ }
187
+ });
188
+ function QuickPreviewRoot({
189
+ options,
190
+ onRequestClose,
191
+ children
192
+ }) {
193
+ var _a2, _b;
194
+ const { top, bottom } = reactNativeSafeAreaContext.useSafeAreaInsets();
195
+ const variant = (_a2 = options == null ? void 0 : options.variant) != null ? _a2 : "popover";
196
+ const dismissOnBackdropPress = (_b = options == null ? void 0 : options.dismissOnBackdropPress) != null ? _b : true;
197
+ const opacity = Animated.useSharedValue(0);
198
+ const cbs = React5__default.default.useRef({
199
+ onOpenStart: options == null ? void 0 : options.onOpenStart,
200
+ onOpenEnd: options == null ? void 0 : options.onOpenEnd,
201
+ onCloseStart: options == null ? void 0 : options.onCloseStart,
202
+ onCloseEnd: options == null ? void 0 : options.onCloseEnd
203
+ });
204
+ React5__default.default.useEffect(() => {
205
+ cbs.current = {
206
+ onOpenStart: options == null ? void 0 : options.onOpenStart,
207
+ onOpenEnd: options == null ? void 0 : options.onOpenEnd,
208
+ onCloseStart: options == null ? void 0 : options.onCloseStart,
209
+ onCloseEnd: options == null ? void 0 : options.onCloseEnd
210
+ };
211
+ }, [options == null ? void 0 : options.onOpenStart, options == null ? void 0 : options.onOpenEnd, options == null ? void 0 : options.onCloseStart, options == null ? void 0 : options.onCloseEnd]);
212
+ React5__default.default.useEffect(() => {
213
+ var _a3, _b2;
214
+ (_b2 = (_a3 = cbs.current).onOpenStart) == null ? void 0 : _b2.call(_a3);
215
+ opacity.value = Animated.withTiming(1, { duration: 180 }, (finished) => {
216
+ var _a4, _b3;
217
+ if (finished) (_b3 = (_a4 = cbs.current).onOpenEnd) == null ? void 0 : _b3.call(_a4);
218
+ });
219
+ return () => {
220
+ var _a4, _b3, _c, _d;
221
+ (_b3 = (_a4 = cbs.current).onCloseStart) == null ? void 0 : _b3.call(_a4);
222
+ (_d = (_c = cbs.current).onCloseEnd) == null ? void 0 : _d.call(_c);
223
+ };
224
+ }, []);
225
+ const containerStyle = Animated.useAnimatedStyle(() => ({ opacity: opacity.value }));
226
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: reactNative.StyleSheet.absoluteFill, pointerEvents: "box-none", accessibilityViewIsModal: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Animated__default.default.View, { style: [reactNative.StyleSheet.absoluteFill, containerStyle], pointerEvents: "box-none", children: [
227
+ /* @__PURE__ */ jsxRuntime.jsx(
228
+ Backdrop,
229
+ {
230
+ onPress: dismissOnBackdropPress ? onRequestClose : void 0,
231
+ dismissOnBackdropPress
232
+ }
233
+ ),
234
+ variant === "sheet" ? /* @__PURE__ */ jsxRuntime.jsx(SheetContainer, { insets: { top, bottom }, options, onRequestClose, children }) : /* @__PURE__ */ jsxRuntime.jsx(PopoverContainer, { insets: { top, bottom }, options, onRequestClose, children })
235
+ ] }) });
236
+ }
237
+
238
+ // src/QuickPreviewAPI.ts
239
+ var STORE = /* @__PURE__ */ Symbol.for("rnqp.controller");
240
+ var g = globalThis;
241
+ var _a;
242
+ var store = (_a = g[STORE]) != null ? _a : g[STORE] = { controller: null };
243
+ function warn() {
244
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
245
+ console.warn("[react-native-quick-preview] PreviewProvider not mounted yet.");
246
+ }
247
+ }
248
+ var QuickPreview = {
249
+ /** @internal Registered by `<PreviewProvider />`. Not part of the public API. */
250
+ _set(c) {
251
+ store.controller = c;
252
+ },
253
+ /**
254
+ * Present `node` as the preview. Replaces the content if one is already open.
255
+ * @param node - the React element to show inside the preview.
256
+ * @param opts - presentation options ({@link QuickPreviewOptions}).
257
+ */
258
+ present(node, opts) {
259
+ const c = store.controller;
260
+ c ? c.present(node, opts) : warn();
261
+ },
262
+ /** Dismiss the current preview. No-op if nothing is open. */
263
+ close() {
264
+ const c = store.controller;
265
+ c ? c.close() : warn();
266
+ },
267
+ /** Merge new options into the currently open preview. */
268
+ update(opts) {
269
+ const c = store.controller;
270
+ c ? c.update(opts) : warn();
271
+ },
272
+ /** Whether a preview is currently open. */
273
+ isOpen() {
274
+ var _a2;
275
+ return !!((_a2 = store.controller) == null ? void 0 : _a2.isOpen());
276
+ },
277
+ /** @internal Dev/test convenience — don't use in app code. */
278
+ __unsafe_getController() {
279
+ return store.controller;
280
+ }
281
+ };
282
+ var QuickPreviewContext = React5__default.default.createContext(null);
283
+ function PreviewProvider({ children }) {
284
+ const [content, setContent] = React5__default.default.useState(null);
285
+ const [options, setOptions] = React5__default.default.useState(void 0);
286
+ const openRef = React5__default.default.useRef(false);
287
+ const announce = React5__default.default.useCallback((msg) => {
288
+ var _a2, _b;
289
+ try {
290
+ (_b = (_a2 = reactNative.AccessibilityInfo).announceForAccessibility) == null ? void 0 : _b.call(_a2, msg);
291
+ } catch (e) {
292
+ }
293
+ }, []);
294
+ const close = React5__default.default.useCallback(() => {
295
+ if (!openRef.current) return;
296
+ openRef.current = false;
297
+ setContent(null);
298
+ setOptions(void 0);
299
+ announce("Quick preview closed");
300
+ }, [announce]);
301
+ const present = React5__default.default.useCallback(
302
+ (node, opts) => {
303
+ setOptions(opts);
304
+ openRef.current = true;
305
+ setContent(() => node);
306
+ announce("Quick preview opened");
307
+ },
308
+ [announce]
309
+ );
310
+ const update = React5__default.default.useCallback((opts) => {
311
+ setOptions((prev) => __spreadValues(__spreadValues({}, prev), opts));
312
+ }, []);
313
+ React5__default.default.useEffect(() => {
314
+ const sub = reactNative.BackHandler.addEventListener("hardwareBackPress", () => {
315
+ if (openRef.current) {
316
+ close();
317
+ return true;
318
+ }
319
+ return false;
320
+ });
321
+ return () => sub.remove();
322
+ }, [close]);
323
+ const value = React5__default.default.useMemo(
324
+ () => ({ present, close, update, isOpen: () => openRef.current }),
325
+ [present, close, update]
326
+ );
327
+ React5__default.default.useLayoutEffect(() => {
328
+ QuickPreview._set(value);
329
+ return () => QuickPreview._set(null);
330
+ }, [value]);
331
+ return /* @__PURE__ */ jsxRuntime.jsx(QuickPreviewContext.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNativePortalize.Host, { children: [
332
+ children,
333
+ content ? /* @__PURE__ */ jsxRuntime.jsx(reactNativePortalize.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(QuickPreviewRoot, { options, onRequestClose: close, children: content }) }) : null
334
+ ] }) });
335
+ }
336
+ function useQuickPreview() {
337
+ const ctx = React5__default.default.useContext(QuickPreviewContext);
338
+ if (!ctx) throw new Error("useQuickPreview must be used within <PreviewProvider>");
339
+ return ctx;
340
+ }
341
+ function QuickPreview2(_a2) {
342
+ var _b = _a2, {
343
+ visible,
344
+ onClose,
345
+ portal = true,
346
+ children
347
+ } = _b, opts = __objRest(_b, [
348
+ "visible",
349
+ "onClose",
350
+ "portal",
351
+ "children"
352
+ ]);
353
+ if (!visible) return null;
354
+ const node = /* @__PURE__ */ jsxRuntime.jsx(QuickPreviewRoot, { options: opts, onRequestClose: onClose, children });
355
+ return portal ? /* @__PURE__ */ jsxRuntime.jsx(reactNativePortalize.Portal, { children: node }) : node;
356
+ }
357
+ function QuickPreviewScrollView(props) {
358
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.ScrollView, __spreadValues({ nestedScrollEnabled: true }, props));
359
+ }
360
+ function QuickPreviewPressable({
361
+ children,
362
+ onPress,
363
+ renderPreview,
364
+ previewOptions,
365
+ delay = 350,
366
+ scale = 0.98,
367
+ onLongPressStart,
368
+ disabled = false,
369
+ style,
370
+ accessible,
371
+ accessibilityLabel,
372
+ testID
373
+ }) {
374
+ const s = Animated.useSharedValue(1);
375
+ const openPreview = () => {
376
+ onLongPressStart == null ? void 0 : onLongPressStart();
377
+ QuickPreview.present(renderPreview(), __spreadValues({
378
+ variant: "popover",
379
+ dismissOnBackdropPress: true
380
+ }, previewOptions));
381
+ };
382
+ const longPress = reactNativeGestureHandler.Gesture.LongPress().enabled(!disabled).minDuration(delay).onTouchesDown(() => {
383
+ s.value = Animated.withTiming(scale, { duration: 90 });
384
+ }).onFinalize(() => {
385
+ s.value = Animated.withTiming(1, { duration: 120 });
386
+ }).onStart(() => {
387
+ Animated.runOnJS(openPreview)();
388
+ });
389
+ const tap = reactNativeGestureHandler.Gesture.Tap().enabled(!disabled).maxDuration(220).onTouchesDown(() => {
390
+ s.value = Animated.withTiming(scale, { duration: 90 });
391
+ }).onFinalize(() => {
392
+ s.value = Animated.withTiming(1, { duration: 120 });
393
+ }).onEnd(() => {
394
+ if (onPress) Animated.runOnJS(onPress)();
395
+ });
396
+ const gesture = reactNativeGestureHandler.Gesture.Exclusive(longPress, tap);
397
+ const animated = Animated.useAnimatedStyle(() => ({
398
+ transform: [{ scale: s.value }]
399
+ }));
400
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNativeGestureHandler.GestureDetector, { gesture, children: /* @__PURE__ */ jsxRuntime.jsx(
401
+ Animated__default.default.View,
402
+ {
403
+ style: [animated, style],
404
+ accessible,
405
+ accessibilityRole: "button",
406
+ accessibilityLabel,
407
+ testID,
408
+ children
409
+ }
410
+ ) });
411
+ }
412
+
413
+ exports.PreviewProvider = PreviewProvider;
414
+ exports.QuickPreview = QuickPreview;
415
+ exports.QuickPreviewComponent = QuickPreview2;
416
+ exports.QuickPreviewPressable = QuickPreviewPressable;
417
+ exports.QuickPreviewScrollView = QuickPreviewScrollView;
418
+ exports.useQuickPreview = useQuickPreview;
419
+ //# sourceMappingURL=index.js.map
2
420
  //# 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/internal/components/Backdrop.tsx","../src/internal/resolveSize.ts","../src/internal/components/SheetContainer.tsx","../src/internal/components/PopoverContainer.tsx","../src/internal/QuickPreviewRoot.tsx","../src/QuickPreviewAPI.ts","../src/context.tsx","../src/useQuickPreview.ts","../src/headless/QuickPreview.tsx","../src/internal/components/QuickPreviewScrollView.tsx","../src/addons/QuickPreviewPressable.tsx"],"names":["useSharedValue","React","withTiming","useAnimatedStyle","StyleSheet","jsx","Animated","Pressable","_a","Easing","Gesture","runOnJS","GestureDetector","jsxs","View","styles","useSafeAreaInsets","_b","AccessibilityInfo","BackHandler","Host","Portal","QuickPreview","ScrollView"],"mappings":"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","file":"index.js","sourcesContent":["import React from 'react'\nimport { Pressable, StyleSheet } from 'react-native'\nimport Animated, { useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated'\n\nexport function Backdrop({\n onPress,\n dismissOnBackdropPress = true,\n}: {\n onPress?: () => void\n dismissOnBackdropPress?: boolean\n}) {\n const opacity = useSharedValue(0)\n React.useEffect(() => {\n opacity.value = withTiming(1, { duration: 160 })\n return () => { opacity.value = 0 }\n }, [opacity])\n\n const style = useAnimatedStyle(() => ({\n backgroundColor: 'rgba(0,0,0,0.5)',\n ...StyleSheet.absoluteFillObject,\n opacity: opacity.value,\n }))\n\n return (\n <Animated.View style={style} pointerEvents={dismissOnBackdropPress && onPress ? 'auto' : 'none'}>\n {dismissOnBackdropPress && onPress ? (\n <Pressable\n style={StyleSheet.absoluteFill}\n onPress={onPress}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Close preview\"\n />\n ) : null}\n </Animated.View>\n )\n}\n","import type { QuickPreviewSize } from '../types'\n\n/**\n * Turn the public `size` option into container style constraints.\n * 'auto' (or undefined) applies nothing; a number caps the height;\n * an object caps height and/or width.\n */\nexport function resolveSizeStyle(\n size?: QuickPreviewSize\n): { maxHeight?: number; maxWidth?: number } {\n if (size == null || size === 'auto') return {}\n if (typeof size === 'number') return { maxHeight: size }\n const out: { maxHeight?: number; maxWidth?: number } = {}\n if (typeof size.maxHeight === 'number') out.maxHeight = size.maxHeight\n if (typeof size.maxWidth === 'number') out.maxWidth = size.maxWidth\n return out\n}\n","import React from 'react'\nimport { View, StyleSheet } from 'react-native'\nimport Animated, { Easing, useAnimatedStyle, useSharedValue, withTiming, runOnJS } from 'react-native-reanimated'\nimport { Gesture, GestureDetector } from 'react-native-gesture-handler'\nimport type { QuickPreviewOptions } from '../../types'\nimport { resolveSizeStyle } from '../resolveSize'\n\nexport function SheetContainer({\n children,\n options,\n insets,\n onRequestClose,\n}: {\n children: React.ReactNode\n options?: QuickPreviewOptions\n insets: { top: number; bottom: number }\n onRequestClose: () => void\n}) {\n const translateY = useSharedValue(1000)\n const dismissOnPanDown = options?.dismissOnPanDown ?? true\n\n React.useEffect(() => {\n // Smooth slide up, no spring bounce.\n translateY.value = withTiming(0, { duration: 300, easing: Easing.out(Easing.cubic) })\n }, [translateY])\n\n const pan = Gesture.Pan()\n .onUpdate((e) => {\n if (!dismissOnPanDown) return\n translateY.value = Math.max(0, e.translationY)\n })\n .onEnd((e) => {\n const shouldClose = e.velocityY > 1000 || translateY.value > 140\n if (shouldClose) {\n translateY.value = withTiming(800, { duration: 200 }, (finished) => {\n if (finished) runOnJS(onRequestClose)()\n })\n } else {\n translateY.value = withTiming(0, { duration: 240, easing: Easing.out(Easing.cubic) })\n }\n })\n\n const style = useAnimatedStyle(() => ({\n transform: [{ translateY: translateY.value }],\n }))\n\n const sizeStyle = resolveSizeStyle(options?.size)\n\n return (\n <GestureDetector gesture={pan}>\n <Animated.View\n style={[styles.sheet, sizeStyle, style, { paddingBottom: Math.max(insets.bottom, 12) }]}\n accessibilityRole={options?.accessibilityRole}\n accessibilityLabel={options?.accessibilityLabel ?? 'Quick preview'}\n >\n <View style={styles.grabber} />\n {children}\n </Animated.View>\n </GestureDetector>\n )\n}\n\nconst styles = StyleSheet.create({\n sheet: {\n position: 'absolute',\n left: 0,\n right: 0,\n bottom: 0,\n borderTopLeftRadius: 16,\n borderTopRightRadius: 16,\n paddingTop: 8,\n backgroundColor: 'white',\n overflow: 'hidden',\n elevation: 3,\n },\n grabber: {\n alignSelf: 'center',\n width: 40,\n height: 4,\n borderRadius: 2,\n backgroundColor: 'rgba(0,0,0,0.2)',\n marginBottom: 8,\n },\n})\n","import React from 'react'\nimport { View, StyleSheet } from 'react-native'\nimport Animated, { Easing, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated'\nimport type { QuickPreviewOptions } from '../../types'\nimport { resolveSizeStyle } from '../resolveSize'\n\nexport function PopoverContainer({\n children,\n options,\n insets: _insets,\n onRequestClose: _onRequestClose, // kept for API parity with SheetContainer\n}: {\n children: React.ReactNode\n options?: QuickPreviewOptions\n insets: { top: number; bottom: number }\n onRequestClose: () => void\n}) {\n const scale = useSharedValue(0.96)\n const opacity = useSharedValue(0)\n\n React.useEffect(() => {\n // Smooth ease-out, no spring overshoot — a clean, quick \"pop\" in.\n scale.value = withTiming(1, { duration: 200, easing: Easing.out(Easing.cubic) })\n opacity.value = withTiming(1, { duration: 160, easing: Easing.out(Easing.quad) })\n }, [scale, opacity])\n\n const container = useAnimatedStyle(() => ({\n opacity: opacity.value,\n transform: [{ scale: scale.value }],\n }))\n\n const sizeStyle = resolveSizeStyle(options?.size)\n\n return (\n <View style={[StyleSheet.absoluteFill, styles.center]} pointerEvents=\"box-none\">\n <Animated.View\n style={[styles.card, sizeStyle, container]}\n accessibilityRole={options?.accessibilityRole}\n accessibilityLabel={options?.accessibilityLabel ?? 'Quick preview'}\n >\n {children}\n </Animated.View>\n </View>\n )\n}\n\nconst styles = StyleSheet.create({\n center: { justifyContent: 'center', alignItems: 'center' },\n card: {\n maxWidth: 520,\n width: '92%',\n maxHeight: '86%',\n borderRadius: 16,\n backgroundColor: 'white',\n overflow: 'hidden',\n elevation: 3,\n },\n})\n","import React from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport Animated, { useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated'\nimport { useSafeAreaInsets } from 'react-native-safe-area-context'\nimport { QuickPreviewOptions } from '../types'\nimport { Backdrop } from './components/Backdrop'\nimport { SheetContainer } from './components/SheetContainer'\nimport { PopoverContainer } from './components/PopoverContainer'\n\nexport function QuickPreviewRoot({\n options,\n onRequestClose,\n children,\n}: {\n options?: QuickPreviewOptions\n onRequestClose: () => void\n children: React.ReactNode\n}) {\n const { top, bottom } = useSafeAreaInsets()\n const variant = options?.variant ?? 'popover'\n const dismissOnBackdropPress = options?.dismissOnBackdropPress ?? true\n\n const opacity = useSharedValue(0)\n\n const cbs = React.useRef({\n onOpenStart: options?.onOpenStart,\n onOpenEnd: options?.onOpenEnd,\n onCloseStart: options?.onCloseStart,\n onCloseEnd: options?.onCloseEnd,\n })\n React.useEffect(() => {\n cbs.current = {\n onOpenStart: options?.onOpenStart,\n onOpenEnd: options?.onOpenEnd,\n onCloseStart: options?.onCloseStart,\n onCloseEnd: options?.onCloseEnd,\n }\n }, [options?.onOpenStart, options?.onOpenEnd, options?.onCloseStart, options?.onCloseEnd])\n\n React.useEffect(() => {\n cbs.current.onOpenStart?.()\n opacity.value = withTiming(1, { duration: 180 }, finished => {\n if (finished) cbs.current.onOpenEnd?.()\n })\n return () => {\n cbs.current.onCloseStart?.()\n cbs.current.onCloseEnd?.()\n }\n // run once (mount-only effect)\n }, [])\n\n const containerStyle = useAnimatedStyle(() => ({ opacity: opacity.value }))\n\n return (\n <View style={StyleSheet.absoluteFill} pointerEvents=\"box-none\" accessibilityViewIsModal>\n <Animated.View style={[StyleSheet.absoluteFill, containerStyle]} pointerEvents=\"box-none\">\n <Backdrop\n onPress={dismissOnBackdropPress ? onRequestClose : undefined}\n dismissOnBackdropPress={dismissOnBackdropPress}\n />\n {variant === 'sheet' ? (\n <SheetContainer insets={{ top, bottom }} options={options} onRequestClose={onRequestClose}>\n {children}\n </SheetContainer>\n ) : (\n <PopoverContainer insets={{ top, bottom }} options={options} onRequestClose={onRequestClose}>\n {children}\n </PopoverContainer>\n )}\n </Animated.View>\n </View>\n )\n}\n","// src/QuickPreviewAPI.ts\nimport type { QuickPreviewController, QuickPreviewOptions } from './types'\nimport type React from 'react'\n\n// Persist across Fast Refresh / HMR\nconst STORE = Symbol.for('rnqp.controller')\ntype Store = { controller: QuickPreviewController | null }\nconst g = globalThis as Record<symbol, Store | undefined>\nconst store: Store = g[STORE] ?? (g[STORE] = { controller: null })\n\nfunction warn() {\n // __DEV__ is provided by RN/Metro; if TS complains, declare it in a globals.d.ts\n if (typeof __DEV__ !== 'undefined' && __DEV__) {\n // eslint-disable-next-line no-console\n console.warn('[react-native-quick-preview] PreviewProvider not mounted yet.')\n }\n}\n\n/**\n * A static handle to the same controller as {@link useQuickPreview} — callable\n * from anywhere, including outside React (services, store actions, event handlers).\n * Before `<PreviewProvider>` mounts it is a safe no-op (with a dev warning).\n *\n * @example\n * ```ts\n * import { QuickPreview } from 'react-native-quick-preview'\n *\n * QuickPreview.present(<Card />, { variant: 'sheet' })\n * QuickPreview.update({ size: { maxHeight: 480 } })\n * QuickPreview.close()\n * ```\n */\nexport const QuickPreview = {\n /** @internal Registered by `<PreviewProvider />`. Not part of the public API. */\n _set(c: QuickPreviewController | null) {\n store.controller = c\n },\n\n /**\n * Present `node` as the preview. Replaces the content if one is already open.\n * @param node - the React element to show inside the preview.\n * @param opts - presentation options ({@link QuickPreviewOptions}).\n */\n present(node: React.ReactNode, opts?: Partial<QuickPreviewOptions>) {\n const c = store.controller\n c ? c.present(node, opts) : warn()\n },\n\n /** Dismiss the current preview. No-op if nothing is open. */\n close() {\n const c = store.controller\n c ? c.close() : warn()\n },\n\n /** Merge new options into the currently open preview. */\n update(opts: Partial<QuickPreviewOptions>) {\n const c = store.controller\n c ? c.update(opts) : warn()\n },\n\n /** Whether a preview is currently open. */\n isOpen() {\n return !!store.controller?.isOpen()\n },\n\n /** @internal Dev/test convenience — don't use in app code. */\n __unsafe_getController(): QuickPreviewController | null {\n return store.controller\n },\n} as const\n","import React from 'react'\nimport { BackHandler, AccessibilityInfo } from 'react-native'\nimport { Host, Portal } from 'react-native-portalize'\nimport { QuickPreviewOptions, QuickPreviewController } from './types'\nimport { QuickPreviewRoot } from './internal/QuickPreviewRoot'\nimport { QuickPreview as QuickPreviewStatic } from './QuickPreviewAPI'\n\nexport const QuickPreviewContext = React.createContext<QuickPreviewController | null>(null)\n\n/**\n * Hosts the preview layer and registers the controller. Mount this once, near the\n * root of your app, inside a `<GestureHandlerRootView>`. After it's mounted you can\n * present previews via {@link useQuickPreview} or the static `QuickPreview` handle.\n *\n * @example\n * ```tsx\n * <GestureHandlerRootView style={{ flex: 1 }}>\n * <PreviewProvider>\n * <YourApp />\n * </PreviewProvider>\n * </GestureHandlerRootView>\n * ```\n */\nexport function PreviewProvider({ children }: { children: React.ReactNode }) {\n const [content, setContent] = React.useState<React.ReactNode | null>(null)\n const [options, setOptions] = React.useState<QuickPreviewOptions | undefined>(undefined)\n const openRef = React.useRef(false)\n\n const announce = React.useCallback((msg: string) => {\n // eslint-disable-next-line no-empty\n try { AccessibilityInfo.announceForAccessibility?.(msg) } catch {}\n }, [])\n\n const close = React.useCallback(() => {\n if (!openRef.current) return\n openRef.current = false\n setContent(null)\n setOptions(undefined)\n announce('Quick preview closed')\n }, [announce])\n\n const present = React.useCallback(\n (node: React.ReactNode, opts?: Partial<QuickPreviewOptions>) => {\n // Replace, don't merge: options from a previous presentation must not\n // leak into the next one. Merging is what update() is for.\n setOptions(opts)\n openRef.current = true\n setContent(() => node)\n announce('Quick preview opened')\n },\n [announce]\n )\n\n const update = React.useCallback((opts: Partial<QuickPreviewOptions>) => {\n setOptions(prev => ({ ...prev, ...opts }))\n }, [])\n\n React.useEffect(() => {\n const sub = BackHandler.addEventListener('hardwareBackPress', () => {\n if (openRef.current) { close(); return true }\n return false\n })\n return () => sub.remove()\n }, [close])\n\n const value = React.useMemo<QuickPreviewController>(\n () => ({ present, close, update, isOpen: () => openRef.current }),\n [present, close, update]\n )\n\n // Register the static API (layout effect = available ASAP)\n React.useLayoutEffect(() => {\n QuickPreviewStatic._set(value)\n return () => QuickPreviewStatic._set(null)\n }, [value])\n\n return (\n <QuickPreviewContext.Provider value={value}>\n <Host>\n {children}\n {content ? (\n <Portal>\n <QuickPreviewRoot options={options} onRequestClose={close}>\n {content}\n </QuickPreviewRoot>\n </Portal>\n ) : null}\n </Host>\n </QuickPreviewContext.Provider>\n )\n}\n","import React from 'react'\nimport { QuickPreviewContext } from './context'\nimport type { QuickPreviewController } from './types'\n\n/**\n * Access the {@link QuickPreviewController} to open, update, and close previews\n * from inside a React component. Must be called under a mounted `<PreviewProvider>`.\n *\n * @throws if used outside of a `<PreviewProvider>`.\n * @returns the controller: `{ present, close, update, isOpen }`.\n *\n * @example\n * ```tsx\n * function ProductCard({ product }) {\n * const { present } = useQuickPreview()\n * return (\n * <Pressable onLongPress={() => present(<ProductPreview product={product} />, { variant: 'sheet' })}>\n * <Thumbnail source={product.image} />\n * </Pressable>\n * )\n * }\n * ```\n */\nexport function useQuickPreview(): QuickPreviewController {\n const ctx = React.useContext(QuickPreviewContext)\n if (!ctx) throw new Error('useQuickPreview must be used within <PreviewProvider>')\n return ctx\n}\n","import React from 'react'\nimport { Portal } from 'react-native-portalize'\nimport { QuickPreviewOptions } from '../types'\nimport { QuickPreviewRoot } from '../internal/QuickPreviewRoot'\n\n/**\n * Props for the controlled, headless `QuickPreviewComponent`. Extends\n * {@link QuickPreviewOptions} (so `variant`, `size`, `dismissOn*`, and the\n * lifecycle callbacks are all accepted).\n */\nexport type HeadlessQuickPreviewProps = {\n /** Whether the preview is shown. You own this state. */\n visible: boolean\n /** Called when the preview requests to close (backdrop press, swipe, back button). */\n onClose: () => void\n /**\n * Render into a portal above the app. Disable only if you're providing your\n * own host/overlay.\n * @defaultValue `true`\n */\n portal?: boolean\n} & Partial<QuickPreviewOptions> & {\n /** The preview content. */\n children: React.ReactNode\n}\n\n/**\n * A controlled, headless preview component — you own the `visible` state. Useful\n * when you prefer a declarative component over the imperative\n * {@link useQuickPreview} hook or the static `QuickPreview` handle.\n *\n * Exported as `QuickPreviewComponent`.\n *\n * @example\n * ```tsx\n * const [visible, setVisible] = useState(false)\n * <QuickPreviewComponent visible={visible} onClose={() => setVisible(false)} variant=\"sheet\">\n * <Card />\n * </QuickPreviewComponent>\n * ```\n */\nexport function QuickPreview({\n visible,\n onClose,\n portal = true,\n children,\n ...opts\n}: HeadlessQuickPreviewProps) {\n if (!visible) return null\n const node = (\n <QuickPreviewRoot options={opts} onRequestClose={onClose}>\n {children}\n </QuickPreviewRoot>\n )\n return portal ? <Portal>{node}</Portal> : node\n}\n","import React from 'react'\nimport { ScrollView, ScrollViewProps } from 'react-native'\n\n/**\n * A gesture-aware `ScrollView` for use inside preview content. Use it instead of\n * a plain `ScrollView` so that scrolling the content and the swipe-to-dismiss\n * gesture don't fight each other. Accepts all `ScrollViewProps`.\n *\n * @example\n * ```tsx\n * present(\n * <QuickPreviewScrollView>\n * <LongArticle />\n * </QuickPreviewScrollView>,\n * { variant: 'sheet', size: { maxHeight: 520 } }\n * )\n * ```\n */\nexport function QuickPreviewScrollView(props: ScrollViewProps) {\n return <ScrollView nestedScrollEnabled {...props} />\n}\n","import React from 'react'\nimport type { StyleProp, ViewStyle } from 'react-native'\nimport { Gesture, GestureDetector } from 'react-native-gesture-handler'\nimport Animated, {\n runOnJS,\n useAnimatedStyle,\n useSharedValue,\n withTiming,\n} from 'react-native-reanimated'\nimport { QuickPreview } from '../QuickPreviewAPI'\nimport type { QuickPreviewOptions } from '../types'\n\nexport type QuickPreviewPressableProps = {\n children: React.ReactNode\n /** Called for a normal tap (e.g., navigate) */\n onPress?: () => void\n /** Return the preview node to present */\n renderPreview: () => React.ReactNode\n /** Options forwarded to QuickPreview.present */\n previewOptions?: Partial<QuickPreviewOptions>\n /** Long-press delay (ms). Default 350 */\n delay?: number\n /** Press-down scale. Default 0.98 */\n scale?: number\n /**\n * Called on the JS thread when the long press activates, right before the\n * preview opens. Wire up haptics here, e.g.:\n * onLongPressStart={() => Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium)}\n * The library deliberately does not import expo-haptics itself: an optional\n * require would break Metro bundling for apps that don't have it installed.\n */\n onLongPressStart?: () => void\n /** Disable all interactions */\n disabled?: boolean\n /** Style applied to the animated wrapper (the thing that scales) */\n style?: StyleProp<ViewStyle>\n /** Accessibility */\n accessible?: boolean\n accessibilityLabel?: string\n testID?: string\n}\n\nexport function QuickPreviewPressable({\n children,\n onPress,\n renderPreview,\n previewOptions,\n delay = 350,\n scale = 0.98,\n onLongPressStart,\n disabled = false,\n style,\n accessible,\n accessibilityLabel,\n testID,\n}: QuickPreviewPressableProps) {\n const s = useSharedValue(1)\n\n // Runs on the JS thread: renderPreview() creates React elements, which must\n // never happen on the UI thread inside a worklet.\n const openPreview = () => {\n onLongPressStart?.()\n QuickPreview.present(renderPreview(), {\n variant: 'popover',\n dismissOnBackdropPress: true,\n ...previewOptions,\n })\n }\n\n const longPress = Gesture.LongPress()\n .enabled(!disabled)\n .minDuration(delay)\n .onTouchesDown(() => {\n s.value = withTiming(scale, { duration: 90 })\n })\n .onFinalize(() => {\n s.value = withTiming(1, { duration: 120 })\n })\n .onStart(() => {\n runOnJS(openPreview)()\n })\n\n const tap = Gesture.Tap()\n .enabled(!disabled)\n .maxDuration(220)\n .onTouchesDown(() => {\n s.value = withTiming(scale, { duration: 90 })\n })\n .onFinalize(() => {\n s.value = withTiming(1, { duration: 120 })\n })\n .onEnd(() => {\n if (onPress) runOnJS(onPress)()\n })\n\n const gesture = Gesture.Exclusive(longPress, tap)\n\n const animated = useAnimatedStyle(() => ({\n transform: [{ scale: s.value }],\n }))\n\n return (\n <GestureDetector gesture={gesture}>\n <Animated.View\n style={[animated, style]}\n accessible={accessible}\n accessibilityRole=\"button\"\n accessibilityLabel={accessibilityLabel}\n testID={testID}\n >\n {children}\n </Animated.View>\n </GestureDetector>\n )\n}\n"]}