@oxyhq/bloom 0.55.0 → 0.57.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.
Files changed (90) hide show
  1. package/README.md +32 -1
  2. package/lib/commonjs/bottom-sheet/index.web.js +10 -10
  3. package/lib/commonjs/bottom-sheet/index.web.js.map +1 -1
  4. package/lib/commonjs/dialog/Dialog.js +2 -3
  5. package/lib/commonjs/dialog/Dialog.js.map +1 -1
  6. package/lib/commonjs/dialog/Dialog.web.js +9 -19
  7. package/lib/commonjs/dialog/Dialog.web.js.map +1 -1
  8. package/lib/commonjs/dialog/DialogHeader.js +4 -6
  9. package/lib/commonjs/dialog/DialogHeader.js.map +1 -1
  10. package/lib/commonjs/overlay/index.js +108 -0
  11. package/lib/commonjs/overlay/index.js.map +1 -0
  12. package/lib/commonjs/portal/index.js +4 -1
  13. package/lib/commonjs/portal/index.js.map +1 -1
  14. package/lib/commonjs/provider/index.js +67 -0
  15. package/lib/commonjs/provider/index.js.map +1 -0
  16. package/lib/commonjs/provider/scroll-provider.js +13 -0
  17. package/lib/commonjs/provider/scroll-provider.js.map +1 -0
  18. package/lib/commonjs/provider/scroll-provider.web.js +13 -0
  19. package/lib/commonjs/provider/scroll-provider.web.js.map +1 -0
  20. package/lib/commonjs/tab-bar/TabBarBase.js +10 -6
  21. package/lib/commonjs/tab-bar/TabBarBase.js.map +1 -1
  22. package/lib/commonjs/toast/ToastHost.js +13 -5
  23. package/lib/commonjs/toast/ToastHost.js.map +1 -1
  24. package/lib/commonjs/zoomable-image-gallery/ZoomableImageGallery.js +189 -196
  25. package/lib/commonjs/zoomable-image-gallery/ZoomableImageGallery.js.map +1 -1
  26. package/lib/module/bottom-sheet/index.web.js +10 -10
  27. package/lib/module/bottom-sheet/index.web.js.map +1 -1
  28. package/lib/module/dialog/Dialog.js +2 -3
  29. package/lib/module/dialog/Dialog.js.map +1 -1
  30. package/lib/module/dialog/Dialog.web.js +10 -20
  31. package/lib/module/dialog/Dialog.web.js.map +1 -1
  32. package/lib/module/dialog/DialogHeader.js +4 -6
  33. package/lib/module/dialog/DialogHeader.js.map +1 -1
  34. package/lib/module/overlay/index.js +102 -0
  35. package/lib/module/overlay/index.js.map +1 -0
  36. package/lib/module/portal/index.js +4 -1
  37. package/lib/module/portal/index.js.map +1 -1
  38. package/lib/module/provider/index.js +63 -0
  39. package/lib/module/provider/index.js.map +1 -0
  40. package/lib/module/provider/scroll-provider.js +16 -0
  41. package/lib/module/provider/scroll-provider.js.map +1 -0
  42. package/lib/module/provider/scroll-provider.web.js +5 -0
  43. package/lib/module/provider/scroll-provider.web.js.map +1 -0
  44. package/lib/module/tab-bar/TabBarBase.js +10 -6
  45. package/lib/module/tab-bar/TabBarBase.js.map +1 -1
  46. package/lib/module/toast/ToastHost.js +13 -5
  47. package/lib/module/toast/ToastHost.js.map +1 -1
  48. package/lib/module/zoomable-image-gallery/ZoomableImageGallery.js +178 -185
  49. package/lib/module/zoomable-image-gallery/ZoomableImageGallery.js.map +1 -1
  50. package/lib/typescript/commonjs/bottom-sheet/index.web.d.ts.map +1 -1
  51. package/lib/typescript/commonjs/dialog/Dialog.web.d.ts.map +1 -1
  52. package/lib/typescript/commonjs/overlay/index.d.ts +67 -0
  53. package/lib/typescript/commonjs/overlay/index.d.ts.map +1 -0
  54. package/lib/typescript/commonjs/provider/index.d.ts +45 -0
  55. package/lib/typescript/commonjs/provider/index.d.ts.map +1 -0
  56. package/lib/typescript/commonjs/provider/scroll-provider.d.ts +14 -0
  57. package/lib/typescript/commonjs/provider/scroll-provider.d.ts.map +1 -0
  58. package/lib/typescript/commonjs/provider/scroll-provider.web.d.ts +3 -0
  59. package/lib/typescript/commonjs/provider/scroll-provider.web.d.ts.map +1 -0
  60. package/lib/typescript/commonjs/toast/ToastHost.d.ts.map +1 -1
  61. package/lib/typescript/commonjs/zoomable-image-gallery/ZoomableImageGallery.d.ts.map +1 -1
  62. package/lib/typescript/module/bottom-sheet/index.web.d.ts.map +1 -1
  63. package/lib/typescript/module/dialog/Dialog.web.d.ts.map +1 -1
  64. package/lib/typescript/module/overlay/index.d.ts +67 -0
  65. package/lib/typescript/module/overlay/index.d.ts.map +1 -0
  66. package/lib/typescript/module/provider/index.d.ts +45 -0
  67. package/lib/typescript/module/provider/index.d.ts.map +1 -0
  68. package/lib/typescript/module/provider/scroll-provider.d.ts +14 -0
  69. package/lib/typescript/module/provider/scroll-provider.d.ts.map +1 -0
  70. package/lib/typescript/module/provider/scroll-provider.web.d.ts +3 -0
  71. package/lib/typescript/module/provider/scroll-provider.web.d.ts.map +1 -0
  72. package/lib/typescript/module/toast/ToastHost.d.ts.map +1 -1
  73. package/lib/typescript/module/zoomable-image-gallery/ZoomableImageGallery.d.ts.map +1 -1
  74. package/package.json +23 -1
  75. package/src/__tests__/BloomProvider.web.test.tsx +114 -0
  76. package/src/__tests__/TabBarBlur.test.tsx +6 -1
  77. package/src/__tests__/overlay-pointer-events.test.tsx +124 -0
  78. package/src/__tests__/pointer-events-style-form.test.ts +58 -0
  79. package/src/bottom-sheet/index.web.tsx +13 -8
  80. package/src/dialog/Dialog.tsx +1 -1
  81. package/src/dialog/Dialog.web.tsx +14 -16
  82. package/src/dialog/DialogHeader.tsx +2 -2
  83. package/src/overlay/index.tsx +115 -0
  84. package/src/portal/index.tsx +4 -2
  85. package/src/provider/index.tsx +68 -0
  86. package/src/provider/scroll-provider.ts +13 -0
  87. package/src/provider/scroll-provider.web.ts +2 -0
  88. package/src/tab-bar/TabBarBase.tsx +8 -6
  89. package/src/toast/ToastHost.tsx +10 -5
  90. package/src/zoomable-image-gallery/ZoomableImageGallery.tsx +15 -20
@@ -11,12 +11,13 @@ var _expoBlur = require("expo-blur");
11
11
  var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
12
12
  var _reactNativeGestureHandler = require("react-native-gesture-handler");
13
13
  var _useTheme = require("../theme/use-theme.js");
14
+ var _index = require("../overlay/index.js");
14
15
  var _portal = require("../portal");
15
- var _index = require("../pressable-with-hover/index.js");
16
- var _index2 = require("../icons/index.js");
16
+ var _index2 = require("../pressable-with-hover/index.js");
17
+ var _index3 = require("../icons/index.js");
17
18
  var _zIndex = require("../styles/z-index.js");
18
19
  var _webViewStyle = require("../styles/web-view-style.js");
19
- var _index3 = require("../image-aspect-ratio-cache/index.js");
20
+ var _index4 = require("../image-aspect-ratio-cache/index.js");
20
21
  var _constants = require("./constants.js");
21
22
  var _jsxRuntime = require("react/jsx-runtime");
22
23
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
@@ -80,7 +81,7 @@ const ZoomableImageGalleryInner = /*#__PURE__*/_react.default.forwardRef(({
80
81
  // paging + the dismiss drag so a pan moves the zoomed image instead.
81
82
  const [isZoomed, setIsZoomed] = (0, _react.useState)(false);
82
83
  // Aspect ratio of the OPENING image (drives the open-animation fit box).
83
- const [openRatio, setOpenRatio] = (0, _react.useState)(_index3.DEFAULT_ASPECT_RATIO);
84
+ const [openRatio, setOpenRatio] = (0, _react.useState)(_index4.DEFAULT_ASPECT_RATIO);
84
85
  // Per-image aspect ratios for the pager pages (index-aligned with `images`).
85
86
  const [pageRatios, setPageRatios] = (0, _react.useState)({});
86
87
 
@@ -154,7 +155,7 @@ const ZoomableImageGalleryInner = /*#__PURE__*/_react.default.forwardRef(({
154
155
  // Compute the largest width/height for `ratio` that fits inside `fitBox`
155
156
  // without cropping (contain).
156
157
  const fitForRatio = (0, _react.useCallback)(ratio => {
157
- const safeRatio = ratio > 0 && Number.isFinite(ratio) ? ratio : _index3.DEFAULT_ASPECT_RATIO;
158
+ const safeRatio = ratio > 0 && Number.isFinite(ratio) ? ratio : _index4.DEFAULT_ASPECT_RATIO;
158
159
  let width = fitBox.width;
159
160
  let height = width / safeRatio;
160
161
  if (height > fitBox.height) {
@@ -178,7 +179,7 @@ const ZoomableImageGalleryInner = /*#__PURE__*/_react.default.forwardRef(({
178
179
  // as a caption at the bottom of the viewer (Bluesky-style lightbox footer).
179
180
  const activeAlt = images[activeIndex]?.alt?.trim() || undefined;
180
181
  const ensureRatio = (0, _react.useCallback)((index, uri) => {
181
- const cached = (0, _index3.getAspectRatio)(uri);
182
+ const cached = (0, _index4.getAspectRatio)(uri);
182
183
  if (cached !== undefined) {
183
184
  setPageRatios(prev => prev[index] === cached ? prev : {
184
185
  ...prev,
@@ -186,7 +187,7 @@ const ZoomableImageGalleryInner = /*#__PURE__*/_react.default.forwardRef(({
186
187
  });
187
188
  return;
188
189
  }
189
- void (0, _index3.fetchAspectRatio)(uri).then(ratio => {
190
+ void (0, _index4.fetchAspectRatio)(uri).then(ratio => {
190
191
  setPageRatios(prev => prev[index] === ratio ? prev : {
191
192
  ...prev,
192
193
  [index]: ratio
@@ -303,8 +304,8 @@ const ZoomableImageGalleryInner = /*#__PURE__*/_react.default.forwardRef(({
303
304
  const safeIndex = Math.min(Math.max(index, 0), nextImages.length - 1);
304
305
  const target = nextImages[safeIndex];
305
306
  if (!target) return;
306
- const knownRatio = target.aspectRatio ?? (0, _index3.getAspectRatio)(target.uri);
307
- const ratio = knownRatio ?? _index3.DEFAULT_ASPECT_RATIO;
307
+ const knownRatio = target.aspectRatio ?? (0, _index4.getAspectRatio)(target.uri);
308
+ const ratio = knownRatio ?? _index4.DEFAULT_ASPECT_RATIO;
308
309
  setImages(nextImages);
309
310
  setActiveIndexBoth(safeIndex);
310
311
  setOpenRatio(ratio);
@@ -313,7 +314,7 @@ const ZoomableImageGalleryInner = /*#__PURE__*/_react.default.forwardRef(({
313
314
  // a genuinely-unknown image falls through to `ensureRatio`'s async probe.
314
315
  const initialRatios = {};
315
316
  nextImages.forEach((img, i) => {
316
- const r = img.aspectRatio ?? (0, _index3.getAspectRatio)(img.uri);
317
+ const r = img.aspectRatio ?? (0, _index4.getAspectRatio)(img.uri);
317
318
  if (r !== undefined) initialRatios[i] = r;
318
319
  });
319
320
  setPageRatios(initialRatios);
@@ -321,7 +322,7 @@ const ZoomableImageGalleryInner = /*#__PURE__*/_react.default.forwardRef(({
321
322
 
322
323
  // Resolve the opening ratio if it was not yet known, then re-fit.
323
324
  if (knownRatio === undefined) {
324
- void (0, _index3.fetchAspectRatio)(target.uri).then(resolved => {
325
+ void (0, _index4.fetchAspectRatio)(target.uri).then(resolved => {
325
326
  setOpenRatio(resolved);
326
327
  setPageRatios(prev => ({
327
328
  ...prev,
@@ -388,15 +389,6 @@ const ZoomableImageGalleryInner = /*#__PURE__*/_react.default.forwardRef(({
388
389
  _react.default.useImperativeHandle(ref, () => ({
389
390
  open
390
391
  }), [open]);
391
-
392
- // Tapping the backdrop dismisses. Uses the same Gesture system as every
393
- // other interaction in this component (image tap, pinch, pan, double-tap)
394
- // instead of a plain RN Pressable, so the backdrop isn't the one interaction
395
- // mixing two different event-handling systems under the same
396
- // GestureHandlerRootView.
397
- const backdropTapGesture = (0, _react.useMemo)(() => _reactNativeGestureHandler.Gesture.Tap().onEnd(() => {
398
- (0, _reactNativeReanimated.runOnJS)(handleDismiss)();
399
- }), [handleDismiss]);
400
392
  const panGesture = (0, _react.useMemo)(() => _reactNativeGestureHandler.Gesture.Pan()
401
393
  // Disabled while zoomed so a drag pans the zoomed image (via the
402
394
  // per-page pan gesture) instead of trying to dismiss the whole viewer.
@@ -656,12 +648,13 @@ const ZoomableImageGalleryInner = /*#__PURE__*/_react.default.forwardRef(({
656
648
  document.addEventListener('keydown', handler);
657
649
  return () => document.removeEventListener('keydown', handler);
658
650
  }, [handleDismiss, isOpen, pageTo]);
659
- const renderContent = () => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeGestureHandler.GestureHandlerRootView, {
651
+ const renderContent = () => /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.OverlayRoot, {
660
652
  style: styles.modalContainer,
661
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeGestureHandler.GestureDetector, {
662
- gesture: backdropTapGesture,
663
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
664
- style: _reactNative.StyleSheet.absoluteFill,
653
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeGestureHandler.GestureHandlerRootView, {
654
+ style: _reactNative.StyleSheet.absoluteFill,
655
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_index.Backdrop, {
656
+ onPress: handleDismiss,
657
+ accessibilityLabel: "Close image viewer",
665
658
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(AnimatedBlurView, {
666
659
  intensity: 80,
667
660
  tint: theme.isDark ? 'dark' : 'light',
@@ -673,196 +666,196 @@ const ZoomableImageGalleryInner = /*#__PURE__*/_react.default.forwardRef(({
673
666
  }, backdropStyle]
674
667
  })
675
668
  })
676
- })
677
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeGestureHandler.GestureDetector, {
678
- gesture: panGesture,
679
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeReanimated.default.View, {
680
- style: [_reactNative.StyleSheet.absoluteFill, styles.zoomContainer, {
681
- width: SCREEN_WIDTH,
682
- height: SCREEN_HEIGHT
683
- }, webUserSelectNoneStyle],
684
- pointerEvents: "box-none",
685
- children: [!pagerReady && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
686
- onPress: handleDismiss,
687
- style: webPointerStyle,
688
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(AnimatedImage, {
689
- source: {
690
- uri: images[activeIndex]?.uri
691
- },
692
- contentFit: "contain",
693
- style: [{
694
- width: activeFit.width,
695
- height: activeFit.height,
696
- borderRadius: cornerRadius
697
- }, openImageStyle],
698
- transition: 0,
699
- ...(_reactNative.Platform.OS === 'web' ? {
700
- draggable: false
701
- } : {})
702
- })
703
- }), pagerReady && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
704
- style: [_reactNative.StyleSheet.absoluteFill, pagerContainerStyle],
705
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
706
- ref: pagerRef,
707
- horizontal: true,
708
- pagingEnabled: true
709
- // Frozen while zoomed so a horizontal drag pans the zoomed image
710
- // instead of paging away from it.
711
- ,
712
- scrollEnabled: !isZoomed,
713
- showsHorizontalScrollIndicator: false,
714
- contentOffset: {
715
- x: pendingIndexRef.current * SCREEN_WIDTH,
716
- y: 0
717
- },
718
- onLayout: onPagerLayout,
719
- onMomentumScrollEnd: onPagerScroll,
720
- ...(_reactNative.Platform.OS === 'web' ? {
721
- onScroll: onPagerScroll
722
- } : {}),
723
- scrollEventThrottle: 16,
724
- style: _reactNative.StyleSheet.absoluteFill,
725
- children: images.map((img, idx) => {
726
- const ratio = pageRatios[idx] ?? (0, _index3.getAspectRatio)(img.uri) ?? _index3.DEFAULT_ASPECT_RATIO;
727
- const fit = fitForRatio(ratio);
728
- // Only the active page is zoomable + gesture-wrapped (double-tap
729
- // / single-tap dismiss / pinch / pan). Off-screen pages stay a
730
- // plain image; the active image handles its own tap-to-dismiss
731
- // through the gesture, so it isn't wrapped in a Pressable.
732
- if (idx === activeIndex) {
669
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeGestureHandler.GestureDetector, {
670
+ gesture: panGesture,
671
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeReanimated.default.View, {
672
+ style: [_reactNative.StyleSheet.absoluteFill, styles.zoomContainer, {
673
+ width: SCREEN_WIDTH,
674
+ height: SCREEN_HEIGHT
675
+ }, webUserSelectNoneStyle],
676
+ pointerEvents: "box-none",
677
+ children: [!pagerReady && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
678
+ onPress: handleDismiss,
679
+ style: webPointerStyle,
680
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(AnimatedImage, {
681
+ source: {
682
+ uri: images[activeIndex]?.uri
683
+ },
684
+ contentFit: "contain",
685
+ style: [{
686
+ width: activeFit.width,
687
+ height: activeFit.height,
688
+ borderRadius: cornerRadius
689
+ }, openImageStyle],
690
+ transition: 0,
691
+ ...(_reactNative.Platform.OS === 'web' ? {
692
+ draggable: false
693
+ } : {})
694
+ })
695
+ }), pagerReady && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
696
+ style: [_reactNative.StyleSheet.absoluteFill, pagerContainerStyle],
697
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
698
+ ref: pagerRef,
699
+ horizontal: true,
700
+ pagingEnabled: true
701
+ // Frozen while zoomed so a horizontal drag pans the zoomed image
702
+ // instead of paging away from it.
703
+ ,
704
+ scrollEnabled: !isZoomed,
705
+ showsHorizontalScrollIndicator: false,
706
+ contentOffset: {
707
+ x: pendingIndexRef.current * SCREEN_WIDTH,
708
+ y: 0
709
+ },
710
+ onLayout: onPagerLayout,
711
+ onMomentumScrollEnd: onPagerScroll,
712
+ ...(_reactNative.Platform.OS === 'web' ? {
713
+ onScroll: onPagerScroll
714
+ } : {}),
715
+ scrollEventThrottle: 16,
716
+ style: _reactNative.StyleSheet.absoluteFill,
717
+ children: images.map((img, idx) => {
718
+ const ratio = pageRatios[idx] ?? (0, _index4.getAspectRatio)(img.uri) ?? _index4.DEFAULT_ASPECT_RATIO;
719
+ const fit = fitForRatio(ratio);
720
+ // Only the active page is zoomable + gesture-wrapped (double-tap
721
+ // / single-tap dismiss / pinch / pan). Off-screen pages stay a
722
+ // plain image; the active image handles its own tap-to-dismiss
723
+ // through the gesture, so it isn't wrapped in a Pressable.
724
+ if (idx === activeIndex) {
725
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
726
+ style: [styles.page, {
727
+ width: SCREEN_WIDTH,
728
+ height: SCREEN_HEIGHT
729
+ }, webPointerStyle],
730
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeGestureHandler.GestureDetector, {
731
+ gesture: activePageGesture,
732
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(AnimatedImage, {
733
+ source: {
734
+ uri: img.uri
735
+ },
736
+ contentFit: "contain",
737
+ style: [{
738
+ width: fit.width,
739
+ height: fit.height,
740
+ borderRadius: cornerRadius
741
+ }, zoomImageStyle],
742
+ transition: 0,
743
+ ...(_reactNative.Platform.OS === 'web' ? {
744
+ draggable: false
745
+ } : {})
746
+ })
747
+ })
748
+ }, `${img.uri}-${idx}`);
749
+ }
733
750
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
734
751
  style: [styles.page, {
735
752
  width: SCREEN_WIDTH,
736
753
  height: SCREEN_HEIGHT
737
- }, webPointerStyle],
738
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeGestureHandler.GestureDetector, {
739
- gesture: activePageGesture,
740
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(AnimatedImage, {
741
- source: {
742
- uri: img.uri
743
- },
744
- contentFit: "contain",
745
- style: [{
746
- width: fit.width,
747
- height: fit.height,
748
- borderRadius: cornerRadius
749
- }, zoomImageStyle],
750
- transition: 0,
751
- ...(_reactNative.Platform.OS === 'web' ? {
752
- draggable: false
753
- } : {})
754
- })
754
+ }],
755
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_expoImage.Image, {
756
+ source: {
757
+ uri: img.uri
758
+ },
759
+ contentFit: "contain",
760
+ style: {
761
+ width: fit.width,
762
+ height: fit.height,
763
+ borderRadius: cornerRadius
764
+ },
765
+ transition: 0,
766
+ ...(_reactNative.Platform.OS === 'web' ? {
767
+ draggable: false
768
+ } : {})
755
769
  })
756
770
  }, `${img.uri}-${idx}`);
757
- }
758
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
759
- style: [styles.page, {
760
- width: SCREEN_WIDTH,
761
- height: SCREEN_HEIGHT
762
- }],
771
+ })
772
+ })
773
+ }), pagerReady && images.length > 1 && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeReanimated.default.View, {
774
+ style: [styles.indicatorWrap, backdropStyle],
775
+ pointerEvents: "box-none",
776
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
777
+ style: styles.counterPill,
778
+ pointerEvents: "none",
779
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
780
+ style: styles.counterText,
781
+ children: `${activeIndex + 1} / ${images.length}`
782
+ })
783
+ }), indicatorVariant === 'thumbnails' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
784
+ horizontal: true,
785
+ showsHorizontalScrollIndicator: false,
786
+ style: styles.thumbStripScroll,
787
+ contentContainerStyle: styles.thumbStripContent,
788
+ children: images.map((img, idx) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
789
+ onPress: () => pageTo(idx),
790
+ accessibilityRole: "button",
791
+ accessibilityLabel: `Go to image ${idx + 1} of ${images.length}`,
792
+ style: [styles.thumbTile, idx === activeIndex ? styles.thumbTileActive : styles.thumbTileInactive, webPointerStyle],
763
793
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_expoImage.Image, {
764
794
  source: {
765
795
  uri: img.uri
766
796
  },
767
- contentFit: "contain",
768
- style: {
769
- width: fit.width,
770
- height: fit.height,
771
- borderRadius: cornerRadius
772
- },
797
+ contentFit: "cover",
798
+ style: styles.thumbTileImage,
773
799
  transition: 0,
774
800
  ...(_reactNative.Platform.OS === 'web' ? {
775
801
  draggable: false
776
802
  } : {})
777
803
  })
778
- }, `${img.uri}-${idx}`);
804
+ }, `thumb-${img.uri}-${idx}`))
805
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
806
+ style: styles.dotsRow,
807
+ pointerEvents: "none",
808
+ children: images.map((img, idx) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
809
+ style: [styles.dot, idx === activeIndex ? styles.dotActive : styles.dotInactive]
810
+ }, `dot-${img.uri}-${idx}`))
811
+ })]
812
+ }), _reactNative.Platform.OS === 'web' && pagerReady && images.length > 1 && activeIndex > 0 && /*#__PURE__*/(0, _jsxRuntime.jsx)(_index2.PressableWithHover, {
813
+ onPress: () => pageTo(activeIndex - 1),
814
+ accessibilityRole: "button",
815
+ accessibilityLabel: "Previous image",
816
+ hitSlop: 8,
817
+ style: [styles.navArrow, styles.navArrowLeft, webPointerStyle],
818
+ hoverStyle: styles.navArrowHoverLeft,
819
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_index3.ArrowLeft_Stroke2_Corner0_Rounded, {
820
+ fill: "#fff",
821
+ size: "lg"
779
822
  })
780
- })
781
- }), pagerReady && images.length > 1 && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeReanimated.default.View, {
782
- style: [styles.indicatorWrap, backdropStyle],
783
- pointerEvents: "box-none",
784
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
785
- style: styles.counterPill,
786
- pointerEvents: "none",
787
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
788
- style: styles.counterText,
789
- children: `${activeIndex + 1} / ${images.length}`
823
+ }), _reactNative.Platform.OS === 'web' && pagerReady && images.length > 1 && activeIndex < images.length - 1 && /*#__PURE__*/(0, _jsxRuntime.jsx)(_index2.PressableWithHover, {
824
+ onPress: () => pageTo(activeIndex + 1),
825
+ accessibilityRole: "button",
826
+ accessibilityLabel: "Next image",
827
+ hitSlop: 8,
828
+ style: [styles.navArrow, styles.navArrowRight, webPointerStyle],
829
+ hoverStyle: styles.navArrowHoverRight,
830
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_index3.ArrowRight_Stroke2_Corner0_Rounded, {
831
+ fill: "#fff",
832
+ size: "lg"
790
833
  })
791
- }), indicatorVariant === 'thumbnails' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
792
- horizontal: true,
793
- showsHorizontalScrollIndicator: false,
794
- style: styles.thumbStripScroll,
795
- contentContainerStyle: styles.thumbStripContent,
796
- children: images.map((img, idx) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
797
- onPress: () => pageTo(idx),
798
- accessibilityRole: "button",
799
- accessibilityLabel: `Go to image ${idx + 1} of ${images.length}`,
800
- style: [styles.thumbTile, idx === activeIndex ? styles.thumbTileActive : styles.thumbTileInactive, webPointerStyle],
801
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_expoImage.Image, {
802
- source: {
803
- uri: img.uri
804
- },
805
- contentFit: "cover",
806
- style: styles.thumbTileImage,
807
- transition: 0,
808
- ...(_reactNative.Platform.OS === 'web' ? {
809
- draggable: false
810
- } : {})
811
- })
812
- }, `thumb-${img.uri}-${idx}`))
813
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
814
- style: styles.dotsRow,
834
+ }), canShare && pagerReady && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
835
+ onPress: handleShare,
836
+ accessibilityRole: "button",
837
+ accessibilityLabel: "Share image",
838
+ hitSlop: 8,
839
+ style: [styles.shareButton, webPointerStyle],
840
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_index3.ArrowOutOfBox_Stroke2_Corner0_Rounded, {
841
+ fill: "#fff",
842
+ size: "md"
843
+ })
844
+ }), activeAlt ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
845
+ style: [styles.altCaptionWrap, images.length > 1 && styles.altCaptionWrapWithIndicator, backdropStyle],
815
846
  pointerEvents: "none",
816
- children: images.map((img, idx) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
817
- style: [styles.dot, idx === activeIndex ? styles.dotActive : styles.dotInactive]
818
- }, `dot-${img.uri}-${idx}`))
819
- })]
820
- }), _reactNative.Platform.OS === 'web' && pagerReady && images.length > 1 && activeIndex > 0 && /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.PressableWithHover, {
821
- onPress: () => pageTo(activeIndex - 1),
822
- accessibilityRole: "button",
823
- accessibilityLabel: "Previous image",
824
- hitSlop: 8,
825
- style: [styles.navArrow, styles.navArrowLeft, webPointerStyle],
826
- hoverStyle: styles.navArrowHoverLeft,
827
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_index2.ArrowLeft_Stroke2_Corner0_Rounded, {
828
- fill: "#fff",
829
- size: "lg"
830
- })
831
- }), _reactNative.Platform.OS === 'web' && pagerReady && images.length > 1 && activeIndex < images.length - 1 && /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.PressableWithHover, {
832
- onPress: () => pageTo(activeIndex + 1),
833
- accessibilityRole: "button",
834
- accessibilityLabel: "Next image",
835
- hitSlop: 8,
836
- style: [styles.navArrow, styles.navArrowRight, webPointerStyle],
837
- hoverStyle: styles.navArrowHoverRight,
838
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_index2.ArrowRight_Stroke2_Corner0_Rounded, {
839
- fill: "#fff",
840
- size: "lg"
841
- })
842
- }), canShare && pagerReady && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
843
- onPress: handleShare,
844
- accessibilityRole: "button",
845
- accessibilityLabel: "Share image",
846
- hitSlop: 8,
847
- style: [styles.shareButton, webPointerStyle],
848
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_index2.ArrowOutOfBox_Stroke2_Corner0_Rounded, {
849
- fill: "#fff",
850
- size: "md"
851
- })
852
- }), activeAlt ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
853
- style: [styles.altCaptionWrap, images.length > 1 && styles.altCaptionWrapWithIndicator, backdropStyle],
854
- pointerEvents: "none",
855
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
856
- style: styles.altCaptionPill,
857
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
858
- style: styles.altCaptionText,
859
- numberOfLines: 4,
860
- children: activeAlt
847
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
848
+ style: styles.altCaptionPill,
849
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
850
+ style: styles.altCaptionText,
851
+ numberOfLines: 4,
852
+ children: activeAlt
853
+ })
861
854
  })
862
- })
863
- }) : null]
864
- })
865
- })]
855
+ }) : null]
856
+ })
857
+ })]
858
+ })
866
859
  });
867
860
  if (!isOpen) return null;
868
861