react-native-gesture-image-viewer 3.0.0-beta.2 → 3.0.0-beta.3

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 (51) hide show
  1. package/lib/module/GestureViewer.js +8 -1
  2. package/lib/module/GestureViewer.js.map +1 -1
  3. package/lib/module/GestureViewerManager.js +32 -10
  4. package/lib/module/GestureViewerManager.js.map +1 -1
  5. package/lib/module/index.js.map +1 -1
  6. package/lib/module/itemDimensions.js +86 -0
  7. package/lib/module/itemDimensions.js.map +1 -0
  8. package/lib/module/useGestureViewer.js +127 -10
  9. package/lib/module/useGestureViewer.js.map +1 -1
  10. package/lib/module/useGestureViewerManagerBridge.js +11 -2
  11. package/lib/module/useGestureViewerManagerBridge.js.map +1 -1
  12. package/lib/module/useWebClickHandler.js.map +1 -1
  13. package/lib/module/useWebClickHandler.web.js +9 -1
  14. package/lib/module/useWebClickHandler.web.js.map +1 -1
  15. package/lib/module/utils/index.js +27 -7
  16. package/lib/module/utils/index.js.map +1 -1
  17. package/lib/module/utils/tapZoom.js +47 -14
  18. package/lib/module/utils/tapZoom.js.map +1 -1
  19. package/lib/typescript/src/GestureViewer.d.ts.map +1 -1
  20. package/lib/typescript/src/GestureViewerManager.d.ts +12 -1
  21. package/lib/typescript/src/GestureViewerManager.d.ts.map +1 -1
  22. package/lib/typescript/src/index.d.ts +1 -1
  23. package/lib/typescript/src/index.d.ts.map +1 -1
  24. package/lib/typescript/src/itemDimensions.d.ts +26 -0
  25. package/lib/typescript/src/itemDimensions.d.ts.map +1 -0
  26. package/lib/typescript/src/types.d.ts +28 -0
  27. package/lib/typescript/src/types.d.ts.map +1 -1
  28. package/lib/typescript/src/useGestureViewer.d.ts +3 -2
  29. package/lib/typescript/src/useGestureViewer.d.ts.map +1 -1
  30. package/lib/typescript/src/useGestureViewerManagerBridge.d.ts +3 -1
  31. package/lib/typescript/src/useGestureViewerManagerBridge.d.ts.map +1 -1
  32. package/lib/typescript/src/useWebClickHandler.d.ts +2 -0
  33. package/lib/typescript/src/useWebClickHandler.d.ts.map +1 -1
  34. package/lib/typescript/src/useWebClickHandler.web.d.ts +4 -2
  35. package/lib/typescript/src/useWebClickHandler.web.d.ts.map +1 -1
  36. package/lib/typescript/src/utils/index.d.ts +4 -2
  37. package/lib/typescript/src/utils/index.d.ts.map +1 -1
  38. package/lib/typescript/src/utils/tapZoom.d.ts +17 -1
  39. package/lib/typescript/src/utils/tapZoom.d.ts.map +1 -1
  40. package/package.json +1 -1
  41. package/src/GestureViewer.tsx +16 -2
  42. package/src/GestureViewerManager.ts +47 -15
  43. package/src/index.tsx +4 -0
  44. package/src/itemDimensions.ts +162 -0
  45. package/src/types.ts +38 -0
  46. package/src/useGestureViewer.ts +184 -13
  47. package/src/useGestureViewerManagerBridge.ts +24 -2
  48. package/src/useWebClickHandler.ts +2 -0
  49. package/src/useWebClickHandler.web.ts +12 -0
  50. package/src/utils/index.ts +55 -22
  51. package/src/utils/tapZoom.ts +55 -15
@@ -13,12 +13,30 @@ export type GestureViewerSingleTapEvent<ItemT> = {
13
13
  index: number;
14
14
  item: ItemT;
15
15
  };
16
+ export type GestureViewerItemDimensions = Readonly<{
17
+ /**
18
+ * Natural/source content width. Must be finite and greater than zero.
19
+ */
20
+ width: number;
21
+ /**
22
+ * Natural/source content height. Must be finite and greater than zero.
23
+ */
24
+ height: number;
25
+ }>;
26
+ export type GestureViewerItemDimensionsResolver<ItemT> = (item: ItemT, index: number) => GestureViewerItemDimensions | undefined;
27
+ export type GestureViewerItemKey = string | number;
28
+ export type GestureViewerItemKeyResolver<ItemT> = (item: ItemT, index: number) => GestureViewerItemKey;
16
29
  export type GestureViewerRenderItemInfo = {
17
30
  /**
18
31
  * Whether the rendered item is currently active.
19
32
  * @remarks The current item remains active during a page transition. When the transition finishes on another item, that item becomes active.
20
33
  */
21
34
  readonly isActive: boolean;
35
+ /**
36
+ * Registers natural/source dimensions for the rendered item after they become available.
37
+ * @remarks Call this from an image load or event callback, or from a passive `useEffect` after commit. Do not call it during render or from a descendant layout effect.
38
+ */
39
+ readonly setItemDimensions: (dimensions: GestureViewerItemDimensions) => void;
22
40
  };
23
41
  export type GestureViewerDismissDirection = 'down' | 'up' | 'both';
24
42
  export interface TriggerAnimationConfig extends WithTimingConfig {
@@ -77,6 +95,16 @@ export interface GestureViewerProps<ItemT> {
77
95
  * - Prefer this callback over overlaying a pressable in `renderContainer` for fullscreen tap handling.
78
96
  */
79
97
  onSingleTap?: (event: GestureViewerSingleTapEvent<ItemT>) => void;
98
+ /**
99
+ * Returns natural/source dimensions for an item when they are already known.
100
+ * @remarks Return `undefined` while dimensions are unavailable. Invalid dimensions fall back to the viewer cell size.
101
+ */
102
+ getItemDimensions?: GestureViewerItemDimensionsResolver<ItemT>;
103
+ /**
104
+ * Returns a stable logical key for an item when the same logical item may be recreated as a new object.
105
+ * @remarks Use this when item identity is not object-stable across rerenders. The key must identify the same rendered content and change when the rendered source or natural dimensions change. Do not return the array index alone. When omitted, runtime dimensions are only reused for the exact same item object.
106
+ */
107
+ getItemKey?: GestureViewerItemKeyResolver<ItemT>;
80
108
  /**
81
109
  * A callback function that is called to render the container.
82
110
  * @remarks Useful for composing additional UI (e.g., close button, toolbars) around the viewer.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import type { GestureViewerProps } from './types';
1
+ import type { GestureViewerItemDimensions, GestureViewerProps } from './types';
2
2
  type UseGestureViewerProps<ItemT> = Omit<GestureViewerProps<ItemT>, 'renderItem' | 'renderContainer' | 'containerStyle' | 'backdropStyle'>;
3
- export declare const useGestureViewer: <ItemT>({ data, initialIndex, onDismiss, onSingleTap, width: customWidth, dismiss, enableDoubleTapZoom, enablePinchZoom, horizontalSwipe, enablePanWhenZoomed, enableLoop, maxZoomScale, pageSpacing, windowSize, height: customHeight, id, onDismissStart, triggerAnimation, autoPlay, autoPlayInterval, }: UseGestureViewerProps<ItemT>) => {
3
+ export declare const useGestureViewer: <ItemT>({ data, initialIndex, onDismiss, onSingleTap, width: customWidth, dismiss, enableDoubleTapZoom, enablePinchZoom, horizontalSwipe, enablePanWhenZoomed, enableLoop, maxZoomScale, pageSpacing, windowSize, height: customHeight, id, onDismissStart, triggerAnimation, autoPlay, autoPlayInterval, getItemDimensions, getItemKey, }: UseGestureViewerProps<ItemT>) => {
4
4
  animatedStyle: import("react-native-reanimated/lib/typescript/hook/commonTypes").AnimatedStyleHandle<{
5
5
  opacity: number;
6
6
  transform: ({
@@ -41,6 +41,7 @@ export declare const useGestureViewer: <ItemT>({ data, initialIndex, onDismiss,
41
41
  pageStride: number;
42
42
  renderWindowSlots: import("./renderWindow").RenderWindowSlot<ItemT>[];
43
43
  visualPage: import("react-native-reanimated").SharedValue<number>;
44
+ setItemDimensions: (index: number, item: ItemT, dimensions: GestureViewerItemDimensions) => void;
44
45
  zoomGesture: import("react-native-gesture-handler/lib/typescript/handlers/gestures/gestureComposition").ExclusiveGesture;
45
46
  zoomPinchGesture: import("react-native-gesture-handler/lib/typescript/handlers/gestures/pinchGesture").PinchGesture;
46
47
  };
@@ -1 +1 @@
1
- {"version":3,"file":"useGestureViewer.d.ts","sourceRoot":"","sources":["../../../src/useGestureViewer.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,kBAAkB,EAAe,MAAM,SAAS,CAAC;AAgB/D,KAAK,qBAAqB,CAAC,KAAK,IAAI,IAAI,CACtC,kBAAkB,CAAC,KAAK,CAAC,EACzB,YAAY,GAAG,iBAAiB,GAAG,gBAAgB,GAAG,eAAe,CACtE,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,KAAK,EAAE,qSAqBrC,qBAAqB,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+pC9B,CAAC"}
1
+ {"version":3,"file":"useGestureViewer.d.ts","sourceRoot":"","sources":["../../../src/useGestureViewer.ts"],"names":[],"mappings":"AAyCA,OAAO,KAAK,EAAE,2BAA2B,EAAE,kBAAkB,EAAe,MAAM,SAAS,CAAC;AAgB5F,KAAK,qBAAqB,CAAC,KAAK,IAAI,IAAI,CACtC,kBAAkB,CAAC,KAAK,CAAC,EACzB,YAAY,GAAG,iBAAiB,GAAG,gBAAgB,GAAG,eAAe,CACtE,CAAC;AAmBF,eAAO,MAAM,gBAAgB,GAAI,KAAK,EAAE,oUAuBrC,qBAAqB,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+BA0MnB,MAAM,QAAQ,KAAK,cAAc,2BAA2B;;;CAumCvE,CAAC"}
@@ -4,6 +4,8 @@ import type GestureViewerManager from './GestureViewerManager';
4
4
  import type { GestureViewerNavigationOptions } from './GestureViewerManager';
5
5
  type UseGestureViewerManagerBridgeOptions = {
6
6
  currentIndexRef: RefObject<number>;
7
+ contentHeight: SharedValue<number>;
8
+ contentWidth: SharedValue<number>;
7
9
  dataLengthRef: RefObject<number>;
8
10
  goToIndex: (index: number, options?: GestureViewerNavigationOptions) => void;
9
11
  goToNext: () => void;
@@ -23,6 +25,6 @@ type UseGestureViewerManagerBridgeOptions = {
23
25
  /**
24
26
  * Owns the registry-to-manager bridge side effects for one viewer instance.
25
27
  */
26
- export declare function useGestureViewerManagerBridge({ currentIndexRef, dataLengthRef, goToIndex, goToNext, goToPrevious, hasRotationChangeListeners, hasZoomChangeListeners, height, id, managerRef, maxZoomScale, rotation, scale, translateX, translateY, width, }: UseGestureViewerManagerBridgeOptions): void;
28
+ export declare function useGestureViewerManagerBridge({ currentIndexRef, contentHeight, contentWidth, dataLengthRef, goToIndex, goToNext, goToPrevious, hasRotationChangeListeners, hasZoomChangeListeners, height, id, managerRef, maxZoomScale, rotation, scale, translateX, translateY, width, }: UseGestureViewerManagerBridgeOptions): void;
27
29
  export {};
28
30
  //# sourceMappingURL=useGestureViewerManagerBridge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useGestureViewerManagerBridge.d.ts","sourceRoot":"","sources":["../../../src/useGestureViewerManagerBridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,KAAK,oBAAoB,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AAG7E,KAAK,oCAAoC,GAAG;IAC1C,eAAe,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IACnC,aAAa,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IACjC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,8BAA8B,KAAK,IAAI,CAAC;IAC7E,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,0BAA0B,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IACjD,sBAAsB,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,SAAS,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IACnD,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC9B,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3B,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,EAC5C,eAAe,EACf,aAAa,EACb,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,0BAA0B,EAC1B,sBAAsB,EACtB,MAAM,EACN,EAAE,EACF,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,KAAK,EACL,UAAU,EACV,UAAU,EACV,KAAK,GACN,EAAE,oCAAoC,QAuEtC"}
1
+ {"version":3,"file":"useGestureViewerManagerBridge.d.ts","sourceRoot":"","sources":["../../../src/useGestureViewerManagerBridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,KAAK,oBAAoB,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AAG7E,KAAK,oCAAoC,GAAG;IAC1C,eAAe,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IACnC,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,aAAa,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IACjC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,8BAA8B,KAAK,IAAI,CAAC;IAC7E,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,0BAA0B,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IACjD,sBAAsB,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,SAAS,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IACnD,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC9B,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3B,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,EAC5C,eAAe,EACf,aAAa,EACb,YAAY,EACZ,aAAa,EACb,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,0BAA0B,EAC1B,sBAAsB,EACtB,MAAM,EACN,EAAE,EACF,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,KAAK,EACL,UAAU,EACV,UAAU,EACV,KAAK,GACN,EAAE,oCAAoC,QAyFtC"}
@@ -19,6 +19,8 @@ export type WebClickHandler = (event: WebClickEvent) => void;
19
19
  export type EmitSingleTap<ItemT> = (x: number, y: number, tapTarget?: WebTapTarget<ItemT>) => void;
20
20
  export type WebClickHandlerConfig<ItemT> = {
21
21
  clearPendingWebSingleTap: () => void;
22
+ contentHeight: SharedValue<number>;
23
+ contentWidth: SharedValue<number>;
22
24
  emitSingleTap: EmitSingleTap<ItemT>;
23
25
  enableDoubleTapZoom: boolean;
24
26
  getCurrentTapTarget: () => WebTapTarget<ItemT> | null;
@@ -1 +1 @@
1
- {"version":3,"file":"useWebClickHandler.d.ts","sourceRoot":"","sources":["../../../src/useWebClickHandler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEnE,MAAM,MAAM,YAAY,CAAC,KAAK,IAAI;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,KAAK,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE;QACb,qBAAqB,EAAE,MAAM;YAC3B,IAAI,EAAE,MAAM,CAAC;YACb,GAAG,EAAE,MAAM,CAAC;SACb,CAAC;KACH,CAAC;IACF,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;AAE7D,MAAM,MAAM,aAAa,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;AAEnG,MAAM,MAAM,qBAAqB,CAAC,KAAK,IAAI;IACzC,wBAAwB,EAAE,MAAM,IAAI,CAAC;IACrC,aAAa,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IACpC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,mBAAmB,EAAE,MAAM,YAAY,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,EAAE,MAAM,OAAO,CAAC;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3B,oBAAoB,EAAE,oBAAoB,CAAC;IAC3C,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,qBAAqB,CAAC,KAAK,CAAC,GAAG,eAAe,CAEhG"}
1
+ {"version":3,"file":"useWebClickHandler.d.ts","sourceRoot":"","sources":["../../../src/useWebClickHandler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEnE,MAAM,MAAM,YAAY,CAAC,KAAK,IAAI;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,KAAK,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE;QACb,qBAAqB,EAAE,MAAM;YAC3B,IAAI,EAAE,MAAM,CAAC;YACb,GAAG,EAAE,MAAM,CAAC;SACb,CAAC;KACH,CAAC;IACF,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;AAE7D,MAAM,MAAM,aAAa,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;AAEnG,MAAM,MAAM,qBAAqB,CAAC,KAAK,IAAI;IACzC,wBAAwB,EAAE,MAAM,IAAI,CAAC;IACrC,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,aAAa,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IACpC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,mBAAmB,EAAE,MAAM,YAAY,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,EAAE,MAAM,OAAO,CAAC;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3B,oBAAoB,EAAE,oBAAoB,CAAC;IAC3C,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,qBAAqB,CAAC,KAAK,CAAC,GAAG,eAAe,CAEhG"}
@@ -19,6 +19,8 @@ export type WebClickHandler = (event: WebClickEvent) => void;
19
19
  export type EmitSingleTap<ItemT> = (x: number, y: number, tapTarget?: WebTapTarget<ItemT>) => void;
20
20
  export type WebClickHandlerConfig<ItemT> = {
21
21
  clearPendingWebSingleTap: () => void;
22
+ contentHeight: SharedValue<number>;
23
+ contentWidth: SharedValue<number>;
22
24
  emitSingleTap: EmitSingleTap<ItemT>;
23
25
  enableDoubleTapZoom: boolean;
24
26
  getCurrentTapTarget: () => WebTapTarget<ItemT> | null;
@@ -31,6 +33,6 @@ export type WebClickHandlerConfig<ItemT> = {
31
33
  translateY: SharedValue<number>;
32
34
  width: number;
33
35
  };
34
- export declare function createWebClickHandler<ItemT>({ clearPendingWebSingleTap, emitSingleTap, enableDoubleTapZoom, getCurrentTapTarget, height, isInteractionLocked, maxZoomScale, scale, scheduleWebSingleTap, translateX, translateY, width, }: WebClickHandlerConfig<ItemT>): WebClickHandler;
35
- export declare function useWebClickHandler<ItemT>({ clearPendingWebSingleTap, emitSingleTap, enableDoubleTapZoom, getCurrentTapTarget, height, isInteractionLocked, maxZoomScale, scale, scheduleWebSingleTap, translateX, translateY, width, }: WebClickHandlerConfig<ItemT>): WebClickHandler;
36
+ export declare function createWebClickHandler<ItemT>({ clearPendingWebSingleTap, contentHeight, contentWidth, emitSingleTap, enableDoubleTapZoom, getCurrentTapTarget, height, isInteractionLocked, maxZoomScale, scale, scheduleWebSingleTap, translateX, translateY, width, }: WebClickHandlerConfig<ItemT>): WebClickHandler;
37
+ export declare function useWebClickHandler<ItemT>({ clearPendingWebSingleTap, contentHeight, contentWidth, emitSingleTap, enableDoubleTapZoom, getCurrentTapTarget, height, isInteractionLocked, maxZoomScale, scale, scheduleWebSingleTap, translateX, translateY, width, }: WebClickHandlerConfig<ItemT>): WebClickHandler;
36
38
  //# sourceMappingURL=useWebClickHandler.web.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useWebClickHandler.web.d.ts","sourceRoot":"","sources":["../../../src/useWebClickHandler.web.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAGnE,MAAM,MAAM,YAAY,CAAC,KAAK,IAAI;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,KAAK,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE;QACb,qBAAqB,EAAE,MAAM;YAC3B,IAAI,EAAE,MAAM,CAAC;YACb,GAAG,EAAE,MAAM,CAAC;SACb,CAAC;KACH,CAAC;IACF,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;AAE7D,MAAM,MAAM,aAAa,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;AAEnG,MAAM,MAAM,qBAAqB,CAAC,KAAK,IAAI;IACzC,wBAAwB,EAAE,MAAM,IAAI,CAAC;IACrC,aAAa,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IACpC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,mBAAmB,EAAE,MAAM,YAAY,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,EAAE,MAAM,OAAO,CAAC;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3B,oBAAoB,EAAE,oBAAoB,CAAC;IAC3C,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,EAC3C,wBAAwB,EACxB,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,MAAM,EACN,mBAAmB,EACnB,YAAY,EACZ,KAAK,EACL,oBAAoB,EACpB,UAAU,EACV,UAAU,EACV,KAAK,GACN,EAAE,qBAAqB,CAAC,KAAK,CAAC,GAAG,eAAe,CA2ChD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,EACxC,wBAAwB,EACxB,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,MAAM,EACN,mBAAmB,EACnB,YAAY,EACZ,KAAK,EACL,oBAAoB,EACpB,UAAU,EACV,UAAU,EACV,KAAK,GACN,EAAE,qBAAqB,CAAC,KAAK,CAAC,GAAG,eAAe,CAgChD"}
1
+ {"version":3,"file":"useWebClickHandler.web.d.ts","sourceRoot":"","sources":["../../../src/useWebClickHandler.web.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAGnE,MAAM,MAAM,YAAY,CAAC,KAAK,IAAI;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,KAAK,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE;QACb,qBAAqB,EAAE,MAAM;YAC3B,IAAI,EAAE,MAAM,CAAC;YACb,GAAG,EAAE,MAAM,CAAC;SACb,CAAC;KACH,CAAC;IACF,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;AAE7D,MAAM,MAAM,aAAa,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;AAEnG,MAAM,MAAM,qBAAqB,CAAC,KAAK,IAAI;IACzC,wBAAwB,EAAE,MAAM,IAAI,CAAC;IACrC,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,aAAa,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IACpC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,mBAAmB,EAAE,MAAM,YAAY,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,EAAE,MAAM,OAAO,CAAC;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3B,oBAAoB,EAAE,oBAAoB,CAAC;IAC3C,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,EAC3C,wBAAwB,EACxB,aAAa,EACb,YAAY,EACZ,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,MAAM,EACN,mBAAmB,EACnB,YAAY,EACZ,KAAK,EACL,oBAAoB,EACpB,UAAU,EACV,UAAU,EACV,KAAK,GACN,EAAE,qBAAqB,CAAC,KAAK,CAAC,GAAG,eAAe,CA6ChD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,EACxC,wBAAwB,EACxB,aAAa,EACb,YAAY,EACZ,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,MAAM,EACN,mBAAmB,EACnB,YAAY,EACZ,KAAK,EACL,oBAAoB,EACpB,UAAU,EACV,UAAU,EACV,KAAK,GACN,EAAE,qBAAqB,CAAC,KAAK,CAAC,GAAG,eAAe,CAoChD"}
@@ -1,7 +1,9 @@
1
- export declare const createBoundsConstraint: ({ width, height }: {
1
+ export declare const resolveGeometrySyncTranslationMode: (previousIndex: number | null, nextIndex: number, scale: number) => "constrain" | "none" | "reset";
2
+ export declare const clampTranslationToBounds: ({ width, height, contentWidth, contentHeight, scale, translateX, translateY, }: {
2
3
  width: number;
3
4
  height: number;
4
- }) => ({ scale, translateX, translateY, }: {
5
+ contentWidth?: number;
6
+ contentHeight?: number;
5
7
  translateX: number;
6
8
  translateY: number;
7
9
  scale: number;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,GAChC,mBAAmB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,MACpD,oCAIE;IACD,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;;;CAiBA,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/index.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,kCAAkC,GAC7C,eAAe,MAAM,GAAG,IAAI,EAC5B,WAAW,MAAM,EACjB,OAAO,MAAM,KACZ,WAAW,GAAG,MAAM,GAAG,OAMzB,CAAC;AAQF,eAAO,MAAM,wBAAwB,GAAI,gFAQtC;IACD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;;;CAqBA,CAAC"}
@@ -1,9 +1,25 @@
1
1
  import type { SharedValue } from 'react-native-reanimated';
2
- export declare const applyTapZoomAtPoint: ({ x, y, width, height, maxZoomScale, scale, translateX, translateY, }: {
2
+ export declare const getTapZoomTarget: ({ x, y, width, height, contentWidth, contentHeight, maxZoomScale, scale, }: {
3
3
  x: number;
4
4
  y: number;
5
5
  width: number;
6
6
  height: number;
7
+ contentWidth?: number;
8
+ contentHeight?: number;
9
+ maxZoomScale: number;
10
+ scale: number;
11
+ }) => {
12
+ scale: number;
13
+ translateX: number;
14
+ translateY: number;
15
+ };
16
+ export declare const applyTapZoomAtPoint: ({ x, y, width, height, contentWidth, contentHeight, maxZoomScale, scale, translateX, translateY, }: {
17
+ x: number;
18
+ y: number;
19
+ width: number;
20
+ height: number;
21
+ contentWidth?: number;
22
+ contentHeight?: number;
7
23
  maxZoomScale: number;
8
24
  scale: SharedValue<number>;
9
25
  translateX: SharedValue<number>;
@@ -1 +1 @@
1
- {"version":3,"file":"tapZoom.d.ts","sourceRoot":"","sources":["../../../../src/utils/tapZoom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAG3D,eAAO,MAAM,mBAAmB,GAAI,uEASjC;IACD,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3B,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACjC,SAuBA,CAAC"}
1
+ {"version":3,"file":"tapZoom.d.ts","sourceRoot":"","sources":["../../../../src/utils/tapZoom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAK3D,eAAO,MAAM,gBAAgB,GAAI,4EAS9B;IACD,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;;;;CAgBA,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,oGAWjC;IACD,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3B,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACjC,SAqBA,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-gesture-image-viewer",
3
- "version": "3.0.0-beta.2",
3
+ "version": "3.0.0-beta.3",
4
4
  "description": "🖼️ React Native Image Viewer - Reanimated-powered image gestures with full control",
5
5
  "keywords": [
6
6
  "android",
@@ -11,7 +11,11 @@ import { composeGestureViewerGestures } from './gestureViewerGestures';
11
11
  import { registry } from './GestureViewerRegistry';
12
12
  import { getWebContentProps } from './getWebContentProps';
13
13
  import type { RenderWindowSlot } from './renderWindow';
14
- import type { GestureViewerProps } from './types';
14
+ import type {
15
+ GestureViewerItemDimensions,
16
+ GestureViewerProps,
17
+ GestureViewerRenderItemInfo,
18
+ } from './types';
15
19
  import { useGestureViewer } from './useGestureViewer';
16
20
 
17
21
  type RenderWindowSlotViewProps<ItemT> = {
@@ -20,6 +24,7 @@ type RenderWindowSlotViewProps<ItemT> = {
20
24
  isActive: boolean;
21
25
  pageStride: number;
22
26
  renderItem: GestureViewerProps<ItemT>['renderItem'];
27
+ setItemDimensions: (index: number, item: ItemT, dimensions: GestureViewerItemDimensions) => void;
23
28
  slot: RenderWindowSlot<ItemT>;
24
29
  visualPage: SharedValue<number>;
25
30
  width: number;
@@ -31,10 +36,14 @@ function RenderWindowSlotView<ItemT>({
31
36
  isActive,
32
37
  pageStride,
33
38
  renderItem,
39
+ setItemDimensions,
34
40
  slot,
35
41
  visualPage,
36
42
  width,
37
43
  }: RenderWindowSlotViewProps<ItemT>) {
44
+ const registerItemDimensions = (dimensions: GestureViewerItemDimensions) => {
45
+ setItemDimensions(slot.logicalIndex, slot.item, dimensions);
46
+ };
38
47
  const slotAnimatedStyle = useAnimatedStyle(() => ({
39
48
  transform: [{ translateX: (slot.virtualIndex - visualPage.get()) * pageStride }],
40
49
  }));
@@ -52,7 +61,10 @@ function RenderWindowSlotView<ItemT>({
52
61
  >
53
62
  <Animated.View style={[styles.page, isActive && animatedStyle]}>
54
63
  <View style={[styles.item, { height, width }]}>
55
- {renderItem(slot.item, slot.logicalIndex, { isActive })}
64
+ {renderItem(slot.item, slot.logicalIndex, {
65
+ isActive,
66
+ setItemDimensions: registerItemDimensions,
67
+ } satisfies GestureViewerRenderItemInfo)}
56
68
  </View>
57
69
  </Animated.View>
58
70
  </Animated.View>
@@ -90,6 +102,7 @@ export function GestureViewer<ItemT>({
90
102
  pageStride,
91
103
  renderWindowSlots,
92
104
  visualPage,
105
+ setItemDimensions,
93
106
  zoomGesture,
94
107
  zoomPinchGesture,
95
108
  } = useGestureViewer({
@@ -136,6 +149,7 @@ export function GestureViewer<ItemT>({
136
149
  key={slot.slotKey}
137
150
  pageStride={pageStride}
138
151
  renderItem={renderItem}
152
+ setItemDimensions={setItemDimensions}
139
153
  slot={slot}
140
154
  visualPage={visualPage}
141
155
  width={width}
@@ -6,7 +6,7 @@ import type {
6
6
  GestureViewerEventType,
7
7
  GestureViewerState,
8
8
  } from './types';
9
- import { createBoundsConstraint } from './utils';
9
+ import { clampTranslationToBounds } from './utils';
10
10
 
11
11
  export type GestureViewerNavigationOptions = {
12
12
  animated?: boolean;
@@ -20,6 +20,15 @@ export type GestureViewerNavigationAdapter = {
20
20
 
21
21
  export type GestureViewerStateReader = () => GestureViewerState;
22
22
 
23
+ type ZoomSharedValuesOptions = {
24
+ scale: SharedValue<number>;
25
+ translateX: SharedValue<number>;
26
+ translateY: SharedValue<number>;
27
+ maxZoomScale: number;
28
+ contentWidth?: SharedValue<number>;
29
+ contentHeight?: SharedValue<number>;
30
+ };
31
+
23
32
  type GestureViewerEventListenerPresenceCallback = (
24
33
  eventType: GestureViewerEventType,
25
34
  hasListeners: boolean,
@@ -41,6 +50,8 @@ class GestureViewerManager {
41
50
  private rotation: SharedValue<number> | null = null;
42
51
  private translateX: SharedValue<number> | null = null;
43
52
  private translateY: SharedValue<number> | null = null;
53
+ private contentWidth: SharedValue<number> | null = null;
54
+ private contentHeight: SharedValue<number> | null = null;
44
55
 
45
56
  private listeners = new Set<(state: GestureViewerState) => void>();
46
57
  private eventListeners = new Map<GestureViewerEventType, Set<(data: any) => void>>();
@@ -158,16 +169,20 @@ class GestureViewerManager {
158
169
  this.stateReader = reader ?? DEFAULT_STATE_READER;
159
170
  }
160
171
 
161
- setZoomSharedValues(
162
- scale: SharedValue<number>,
163
- translateX: SharedValue<number>,
164
- translateY: SharedValue<number>,
165
- maxZoomScale: number,
166
- ) {
172
+ setZoomSharedValues({
173
+ scale,
174
+ translateX,
175
+ translateY,
176
+ maxZoomScale,
177
+ contentWidth,
178
+ contentHeight,
179
+ }: ZoomSharedValuesOptions) {
167
180
  this.scale = scale;
168
181
  this.translateX = translateX;
169
182
  this.translateY = translateY;
170
183
  this.maxZoomScale = maxZoomScale;
184
+ this.contentWidth = contentWidth ?? null;
185
+ this.contentHeight = contentHeight ?? null;
171
186
  }
172
187
 
173
188
  notifyStateChange() {
@@ -226,10 +241,7 @@ class GestureViewerManager {
226
241
 
227
242
  this.scale.set(withTiming(nextScale));
228
243
 
229
- const { translateX, translateY } = createBoundsConstraint({
230
- width: this.width,
231
- height: this.height,
232
- })({
244
+ const { translateX, translateY } = this.clampZoomTranslationToBounds({
233
245
  translateX: this.translateX.get(),
234
246
  translateY: this.translateY.get(),
235
247
  scale: nextScale,
@@ -260,10 +272,7 @@ class GestureViewerManager {
260
272
  return;
261
273
  }
262
274
 
263
- const { translateX, translateY } = createBoundsConstraint({
264
- width: this.width,
265
- height: this.height,
266
- })({
275
+ const { translateX, translateY } = this.clampZoomTranslationToBounds({
267
276
  translateX: this.translateX.get(),
268
277
  translateY: this.translateY.get(),
269
278
  scale: nextScale,
@@ -317,14 +326,37 @@ class GestureViewerManager {
317
326
  this.listeners.clear();
318
327
  this.navigationAdapter = null;
319
328
  this.stateReader = DEFAULT_STATE_READER;
329
+ this.width = 0;
330
+ this.height = 0;
320
331
  this.maxZoomScale = 2;
321
332
  this.scale = null;
322
333
  this.translateX = null;
323
334
  this.translateY = null;
324
335
  this.rotation = null;
336
+ this.contentWidth = null;
337
+ this.contentHeight = null;
325
338
  this.eventListeners.clear();
326
339
  this.eventListenerPresenceSubscribers.clear();
327
340
  }
341
+
342
+ private clampZoomTranslationToBounds = ({
343
+ scale,
344
+ translateX,
345
+ translateY,
346
+ }: {
347
+ scale: number;
348
+ translateX: number;
349
+ translateY: number;
350
+ }) =>
351
+ clampTranslationToBounds({
352
+ contentHeight: this.contentHeight?.get(),
353
+ contentWidth: this.contentWidth?.get(),
354
+ height: this.height,
355
+ scale,
356
+ translateX,
357
+ translateY,
358
+ width: this.width,
359
+ });
328
360
  }
329
361
 
330
362
  export default GestureViewerManager;
package/src/index.tsx CHANGED
@@ -6,6 +6,10 @@ export type {
6
6
  GestureViewerEventCallback,
7
7
  GestureViewerEventData,
8
8
  GestureViewerEventType,
9
+ GestureViewerItemDimensions,
10
+ GestureViewerItemDimensionsResolver,
11
+ GestureViewerItemKey,
12
+ GestureViewerItemKeyResolver,
9
13
  GestureViewerProps,
10
14
  GestureViewerRenderItemInfo,
11
15
  GestureViewerState,
@@ -0,0 +1,162 @@
1
+ import type {
2
+ GestureViewerItemDimensions,
3
+ GestureViewerItemDimensionsResolver,
4
+ GestureViewerItemKey,
5
+ GestureViewerItemKeyResolver,
6
+ } from './types';
7
+
8
+ type ItemDimensionsRegistryEntry<ItemT> = Readonly<{
9
+ item: ItemT;
10
+ itemKey?: GestureViewerItemKey;
11
+ dimensions: GestureViewerItemDimensions;
12
+ }>;
13
+
14
+ export type ItemDimensionsRegistry<ItemT> = Map<number, ItemDimensionsRegistryEntry<ItemT>>;
15
+
16
+ export const isValidItemDimensions = (
17
+ dimensions: GestureViewerItemDimensions | null | undefined,
18
+ ): dimensions is GestureViewerItemDimensions => {
19
+ return (
20
+ dimensions !== null &&
21
+ dimensions !== undefined &&
22
+ Number.isFinite(dimensions.width) &&
23
+ Number.isFinite(dimensions.height) &&
24
+ dimensions.width > 0 &&
25
+ dimensions.height > 0
26
+ );
27
+ };
28
+
29
+ const resolveItemKey = <ItemT>(
30
+ getItemKey: GestureViewerItemKeyResolver<ItemT> | undefined,
31
+ item: ItemT,
32
+ index: number,
33
+ ): GestureViewerItemKey | undefined => {
34
+ const itemKey = getItemKey?.(item, index);
35
+
36
+ if (typeof itemKey === 'string') {
37
+ return itemKey;
38
+ }
39
+
40
+ return typeof itemKey === 'number' && Number.isFinite(itemKey) ? itemKey : undefined;
41
+ };
42
+
43
+ const doesEntryMatchItem = <ItemT>(
44
+ entry: ItemDimensionsRegistryEntry<ItemT>,
45
+ item: ItemT,
46
+ itemKey: GestureViewerItemKey | undefined,
47
+ ): boolean => {
48
+ if (itemKey !== undefined && entry.itemKey !== undefined) {
49
+ return entry.itemKey === itemKey;
50
+ }
51
+
52
+ return Object.is(entry.item, item);
53
+ };
54
+
55
+ export const pruneItemDimensionsRegistry = <ItemT>(
56
+ registry: ItemDimensionsRegistry<ItemT>,
57
+ dataLength: number,
58
+ ): void => {
59
+ for (const index of registry.keys()) {
60
+ if (index < 0 || index >= dataLength) {
61
+ registry.delete(index);
62
+ }
63
+ }
64
+ };
65
+
66
+ export const resolveItemDimensions = <ItemT>({
67
+ registry,
68
+ data,
69
+ index,
70
+ getItemDimensions,
71
+ getItemKey,
72
+ }: {
73
+ registry: ItemDimensionsRegistry<ItemT>;
74
+ data: readonly ItemT[];
75
+ index: number;
76
+ getItemDimensions?: GestureViewerItemDimensionsResolver<ItemT>;
77
+ getItemKey?: GestureViewerItemKeyResolver<ItemT>;
78
+ }): GestureViewerItemDimensions | undefined => {
79
+ if (index < 0 || index >= data.length) {
80
+ return undefined;
81
+ }
82
+
83
+ // `as ItemT` restores the viewer's dense-list invariant, which TypeScript cannot infer from
84
+ // generic indexed access when `noUncheckedIndexedAccess` is enabled.
85
+ const item = data[index] as ItemT;
86
+ const registered = registry.get(index);
87
+ const itemKey = registered ? resolveItemKey(getItemKey, item, index) : undefined;
88
+
89
+ if (
90
+ registered &&
91
+ doesEntryMatchItem(registered, item, itemKey) &&
92
+ isValidItemDimensions(registered.dimensions)
93
+ ) {
94
+ return registered.dimensions;
95
+ }
96
+
97
+ const resolved = getItemDimensions?.(item, index);
98
+
99
+ if (isValidItemDimensions(resolved)) {
100
+ return resolved;
101
+ }
102
+
103
+ return undefined;
104
+ };
105
+
106
+ export const registerItemDimensions = <ItemT>({
107
+ registry,
108
+ data,
109
+ index,
110
+ item,
111
+ dimensions,
112
+ getItemKey,
113
+ }: {
114
+ registry: ItemDimensionsRegistry<ItemT>;
115
+ data: readonly ItemT[];
116
+ index: number;
117
+ item: ItemT;
118
+ dimensions: GestureViewerItemDimensions;
119
+ getItemKey?: GestureViewerItemKeyResolver<ItemT>;
120
+ }): 'ignored' | 'unchanged' | 'updated' => {
121
+ if (index < 0 || index >= data.length || !isValidItemDimensions(dimensions)) {
122
+ return 'ignored';
123
+ }
124
+
125
+ // `as ItemT` restores the viewer's dense-list invariant, which TypeScript cannot infer from
126
+ // generic indexed access when `noUncheckedIndexedAccess` is enabled.
127
+ const currentItem = data[index] as ItemT;
128
+ const currentItemKey = resolveItemKey(getItemKey, currentItem, index);
129
+ const reportedItemKey = Object.is(currentItem, item)
130
+ ? currentItemKey
131
+ : resolveItemKey(getItemKey, item, index);
132
+ const hasMatchingKey =
133
+ currentItemKey !== undefined &&
134
+ reportedItemKey !== undefined &&
135
+ currentItemKey === reportedItemKey;
136
+
137
+ if (!Object.is(currentItem, item) && !hasMatchingKey) {
138
+ return 'ignored';
139
+ }
140
+
141
+ const registered = registry.get(index);
142
+
143
+ if (
144
+ registered &&
145
+ doesEntryMatchItem(registered, currentItem, currentItemKey) &&
146
+ registered.dimensions.width === dimensions.width &&
147
+ registered.dimensions.height === dimensions.height
148
+ ) {
149
+ return 'unchanged';
150
+ }
151
+
152
+ registry.set(index, {
153
+ dimensions: {
154
+ height: dimensions.height,
155
+ width: dimensions.width,
156
+ },
157
+ item: currentItem,
158
+ itemKey: currentItemKey,
159
+ });
160
+
161
+ return 'updated';
162
+ };
package/src/types.ts CHANGED
@@ -16,12 +16,40 @@ export type GestureViewerSingleTapEvent<ItemT> = {
16
16
  item: ItemT;
17
17
  };
18
18
 
19
+ export type GestureViewerItemDimensions = Readonly<{
20
+ /**
21
+ * Natural/source content width. Must be finite and greater than zero.
22
+ */
23
+ width: number;
24
+ /**
25
+ * Natural/source content height. Must be finite and greater than zero.
26
+ */
27
+ height: number;
28
+ }>;
29
+
30
+ export type GestureViewerItemDimensionsResolver<ItemT> = (
31
+ item: ItemT,
32
+ index: number,
33
+ ) => GestureViewerItemDimensions | undefined;
34
+
35
+ export type GestureViewerItemKey = string | number;
36
+
37
+ export type GestureViewerItemKeyResolver<ItemT> = (
38
+ item: ItemT,
39
+ index: number,
40
+ ) => GestureViewerItemKey;
41
+
19
42
  export type GestureViewerRenderItemInfo = {
20
43
  /**
21
44
  * Whether the rendered item is currently active.
22
45
  * @remarks The current item remains active during a page transition. When the transition finishes on another item, that item becomes active.
23
46
  */
24
47
  readonly isActive: boolean;
48
+ /**
49
+ * Registers natural/source dimensions for the rendered item after they become available.
50
+ * @remarks Call this from an image load or event callback, or from a passive `useEffect` after commit. Do not call it during render or from a descendant layout effect.
51
+ */
52
+ readonly setItemDimensions: (dimensions: GestureViewerItemDimensions) => void;
25
53
  };
26
54
 
27
55
  export type GestureViewerDismissDirection = 'down' | 'up' | 'both';
@@ -83,6 +111,16 @@ export interface GestureViewerProps<ItemT> {
83
111
  * - Prefer this callback over overlaying a pressable in `renderContainer` for fullscreen tap handling.
84
112
  */
85
113
  onSingleTap?: (event: GestureViewerSingleTapEvent<ItemT>) => void;
114
+ /**
115
+ * Returns natural/source dimensions for an item when they are already known.
116
+ * @remarks Return `undefined` while dimensions are unavailable. Invalid dimensions fall back to the viewer cell size.
117
+ */
118
+ getItemDimensions?: GestureViewerItemDimensionsResolver<ItemT>;
119
+ /**
120
+ * Returns a stable logical key for an item when the same logical item may be recreated as a new object.
121
+ * @remarks Use this when item identity is not object-stable across rerenders. The key must identify the same rendered content and change when the rendered source or natural dimensions change. Do not return the array index alone. When omitted, runtime dimensions are only reused for the exact same item object.
122
+ */
123
+ getItemKey?: GestureViewerItemKeyResolver<ItemT>;
86
124
  /**
87
125
  * A callback function that is called to render the container.
88
126
  * @remarks Useful for composing additional UI (e.g., close button, toolbars) around the viewer.