react-native-gesture-image-viewer 1.2.3 → 1.4.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.
@@ -35,6 +35,10 @@ export const useGestureViewerController = (id = 'default') => {
35
35
  goToIndex: manager?.goToIndex || noopFunction,
36
36
  goToPrevious: manager?.goToPrevious || noopFunction,
37
37
  goToNext: manager?.goToNext || noopFunction,
38
+ zoomIn: manager?.zoomIn || noopFunction,
39
+ zoomOut: manager?.zoomOut || noopFunction,
40
+ resetZoom: manager?.resetZoom || noopFunction,
41
+ rotate: manager?.rotate || noopFunction,
38
42
  currentIndex: state.currentIndex,
39
43
  totalCount: state.dataLength
40
44
  };
@@ -1 +1 @@
1
- {"version":3,"names":["useEffect","useMemo","useRef","useState","registry","useGestureViewerController","id","state","setState","currentIndex","dataLength","manager","setManager","unsubscribeRef","handleManagerChange","newManager","current","getState","subscribe","unsubscribeFromRegistry","subscribeToManager","noopFunction","goToIndex","goToPrevious","goToNext","totalCount"],"sourceRoot":"../../src","sources":["useGestureViewerController.ts"],"mappings":";;AAAA,SAASA,SAAS,EAAEC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,OAAO;AAG5D,SAASC,QAAQ,QAAQ,4BAAyB;AAElD,OAAO,MAAMC,0BAA0B,GAAGA,CAACC,EAAE,GAAG,SAAS,KAAK;EAC5D,MAAM,CAACC,KAAK,EAAEC,QAAQ,CAAC,GAAGL,QAAQ,CAA4B;IAC5DM,YAAY,EAAE,CAAC;IACfC,UAAU,EAAE;EACd,CAAC,CAAC;EAEF,MAAM,CAACC,OAAO,EAAEC,UAAU,CAAC,GAAGT,QAAQ,CAA8B,IAAI,CAAC;EACzE,MAAMU,cAAc,GAAGX,MAAM,CAAsB,IAAI,CAAC;EAExDF,SAAS,CAAC,MAAM;IACd,MAAMc,mBAAmB,GAAIC,UAAuC,IAAK;MACvEF,cAAc,CAACG,OAAO,GAAG,CAAC;MAC1BH,cAAc,CAACG,OAAO,GAAG,IAAI;MAE7BJ,UAAU,CAACG,UAAU,CAAC;MAEtB,IAAIA,UAAU,EAAE;QACdP,QAAQ,CAACO,UAAU,CAACE,QAAQ,CAAC,CAAC,CAAC;QAC/BJ,cAAc,CAACG,OAAO,GAAGD,UAAU,CAACG,SAAS,CAACV,QAAQ,CAAC;QACvD;MACF;MAEAA,QAAQ,CAAC;QAAEC,YAAY,EAAE,CAAC;QAAEC,UAAU,EAAE;MAAE,CAAC,CAAC;IAC9C,CAAC;IAED,MAAMS,uBAAuB,GAAGf,QAAQ,CAACgB,kBAAkB,CAACd,EAAE,EAAEQ,mBAAmB,CAAC;IAEpF,OAAO,MAAM;MACXK,uBAAuB,CAAC,CAAC;MACzBN,cAAc,CAACG,OAAO,GAAG,CAAC;IAC5B,CAAC;EACH,CAAC,EAAE,CAACV,EAAE,CAAC,CAAC;EAER,MAAMe,YAAY,GAAGpB,OAAO,CAAC,MAAM,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC;EAEhD,OAAO;IACLqB,SAAS,EAAEX,OAAO,EAAEW,SAAS,IAAID,YAAY;IAC7CE,YAAY,EAAEZ,OAAO,EAAEY,YAAY,IAAIF,YAAY;IACnDG,QAAQ,EAAEb,OAAO,EAAEa,QAAQ,IAAIH,YAAY;IAC3CZ,YAAY,EAAEF,KAAK,CAACE,YAAY;IAChCgB,UAAU,EAAElB,KAAK,CAACG;EACpB,CAAC;AACH,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["useEffect","useMemo","useRef","useState","registry","useGestureViewerController","id","state","setState","currentIndex","dataLength","manager","setManager","unsubscribeRef","handleManagerChange","newManager","current","getState","subscribe","unsubscribeFromRegistry","subscribeToManager","noopFunction","goToIndex","goToPrevious","goToNext","zoomIn","zoomOut","resetZoom","rotate","totalCount"],"sourceRoot":"../../src","sources":["useGestureViewerController.ts"],"mappings":";;AAAA,SAASA,SAAS,EAAEC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,OAAO;AAG5D,SAASC,QAAQ,QAAQ,4BAAyB;AAElD,OAAO,MAAMC,0BAA0B,GAAGA,CAACC,EAAE,GAAG,SAAS,KAAK;EAC5D,MAAM,CAACC,KAAK,EAAEC,QAAQ,CAAC,GAAGL,QAAQ,CAA4B;IAC5DM,YAAY,EAAE,CAAC;IACfC,UAAU,EAAE;EACd,CAAC,CAAC;EAEF,MAAM,CAACC,OAAO,EAAEC,UAAU,CAAC,GAAGT,QAAQ,CAA8B,IAAI,CAAC;EACzE,MAAMU,cAAc,GAAGX,MAAM,CAAsB,IAAI,CAAC;EAExDF,SAAS,CAAC,MAAM;IACd,MAAMc,mBAAmB,GAAIC,UAAuC,IAAK;MACvEF,cAAc,CAACG,OAAO,GAAG,CAAC;MAC1BH,cAAc,CAACG,OAAO,GAAG,IAAI;MAE7BJ,UAAU,CAACG,UAAU,CAAC;MAEtB,IAAIA,UAAU,EAAE;QACdP,QAAQ,CAACO,UAAU,CAACE,QAAQ,CAAC,CAAC,CAAC;QAC/BJ,cAAc,CAACG,OAAO,GAAGD,UAAU,CAACG,SAAS,CAACV,QAAQ,CAAC;QACvD;MACF;MAEAA,QAAQ,CAAC;QAAEC,YAAY,EAAE,CAAC;QAAEC,UAAU,EAAE;MAAE,CAAC,CAAC;IAC9C,CAAC;IAED,MAAMS,uBAAuB,GAAGf,QAAQ,CAACgB,kBAAkB,CAACd,EAAE,EAAEQ,mBAAmB,CAAC;IAEpF,OAAO,MAAM;MACXK,uBAAuB,CAAC,CAAC;MACzBN,cAAc,CAACG,OAAO,GAAG,CAAC;IAC5B,CAAC;EACH,CAAC,EAAE,CAACV,EAAE,CAAC,CAAC;EAER,MAAMe,YAAY,GAAGpB,OAAO,CAAC,MAAM,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC;EAEhD,OAAO;IACLqB,SAAS,EAAEX,OAAO,EAAEW,SAAS,IAAID,YAAY;IAC7CE,YAAY,EAAEZ,OAAO,EAAEY,YAAY,IAAIF,YAAY;IACnDG,QAAQ,EAAEb,OAAO,EAAEa,QAAQ,IAAIH,YAAY;IAC3CI,MAAM,EAAEd,OAAO,EAAEc,MAAM,IAAIJ,YAAY;IACvCK,OAAO,EAAEf,OAAO,EAAEe,OAAO,IAAIL,YAAY;IACzCM,SAAS,EAAEhB,OAAO,EAAEgB,SAAS,IAAIN,YAAY;IAC7CO,MAAM,EAAEjB,OAAO,EAAEiB,MAAM,IAAIP,YAAY;IACvCZ,YAAY,EAAEF,KAAK,CAACE,YAAY;IAChCoB,UAAU,EAAEtB,KAAK,CAACG;EACpB,CAAC;AACH,CAAC","ignoreList":[]}
@@ -22,4 +22,27 @@ export const isFlashListLike = component => {
22
22
  }
23
23
  return component?.name === 'FlashList';
24
24
  };
25
+ export const createBoundsConstraint = ({
26
+ width,
27
+ height
28
+ }) => ({
29
+ scale,
30
+ translateX,
31
+ translateY
32
+ }) => {
33
+ 'worklet';
34
+
35
+ if (scale <= 1) {
36
+ return {
37
+ translateX,
38
+ translateY
39
+ };
40
+ }
41
+ const maxTranslateX = (width * scale - width) / 2;
42
+ const maxTranslateY = (height * scale - height) / 2;
43
+ return {
44
+ translateX: Math.max(-maxTranslateX, Math.min(maxTranslateX, translateX)),
45
+ translateY: Math.max(-maxTranslateY, Math.min(maxTranslateY, translateY))
46
+ };
47
+ };
25
48
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["FlatList","RNFlatList","ScrollView","RNScrollView","GestureFlatList","GestureScrollView","isScrollViewLike","component","isFlatListLike","isFlashListLike","FlashList","require","name"],"sourceRoot":"../../src","sources":["utils.ts"],"mappings":";;AAAA,SAASA,QAAQ,IAAIC,UAAU,EAAEC,UAAU,IAAIC,YAAY,QAAQ,cAAc;AACjF,SAASH,QAAQ,IAAII,eAAe,EAAEF,UAAU,IAAIG,iBAAiB,QAAQ,8BAA8B;AAG3G,OAAO,MAAMC,gBAAgB,GAAIC,SAAc,IAAuC;EACpF,OAAOA,SAAS,KAAKJ,YAAY,IAAII,SAAS,KAAKF,iBAAiB;AACtE,CAAC;AAED,OAAO,MAAMG,cAAc,GAAID,SAAc,IAAqC;EAChF,IAAIA,SAAS,KAAKN,UAAU,IAAIM,SAAS,KAAKH,eAAe,IAAIK,eAAe,CAACF,SAAS,CAAC,EAAE;IAC3F,OAAO,IAAI;EACb;EAEA,OAAO,KAAK;AACd,CAAC;AAED,OAAO,MAAME,eAAe,GAAIF,SAAc,IAAuB;EACnE,IAAI;IACF,MAAMG,SAAS,GAAGC,OAAO,CAAC,qBAAqB,CAAC,EAAED,SAAS;IAE3D,IAAIA,SAAS,IAAIH,SAAS,KAAKG,SAAS,EAAE;MACxC,OAAO,IAAI;IACb;EACF,CAAC,CAAC,MAAM;IACN;EAAA;EAGF,OAAOH,SAAS,EAAEK,IAAI,KAAK,WAAW;AACxC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["FlatList","RNFlatList","ScrollView","RNScrollView","GestureFlatList","GestureScrollView","isScrollViewLike","component","isFlatListLike","isFlashListLike","FlashList","require","name","createBoundsConstraint","width","height","scale","translateX","translateY","maxTranslateX","maxTranslateY","Math","max","min"],"sourceRoot":"../../src","sources":["utils.ts"],"mappings":";;AAAA,SAASA,QAAQ,IAAIC,UAAU,EAAEC,UAAU,IAAIC,YAAY,QAAQ,cAAc;AACjF,SAASH,QAAQ,IAAII,eAAe,EAAEF,UAAU,IAAIG,iBAAiB,QAAQ,8BAA8B;AAG3G,OAAO,MAAMC,gBAAgB,GAAIC,SAAc,IAAuC;EACpF,OAAOA,SAAS,KAAKJ,YAAY,IAAII,SAAS,KAAKF,iBAAiB;AACtE,CAAC;AAED,OAAO,MAAMG,cAAc,GAAID,SAAc,IAAqC;EAChF,IAAIA,SAAS,KAAKN,UAAU,IAAIM,SAAS,KAAKH,eAAe,IAAIK,eAAe,CAACF,SAAS,CAAC,EAAE;IAC3F,OAAO,IAAI;EACb;EAEA,OAAO,KAAK;AACd,CAAC;AAED,OAAO,MAAME,eAAe,GAAIF,SAAc,IAAuB;EACnE,IAAI;IACF,MAAMG,SAAS,GAAGC,OAAO,CAAC,qBAAqB,CAAC,EAAED,SAAS;IAE3D,IAAIA,SAAS,IAAIH,SAAS,KAAKG,SAAS,EAAE;MACxC,OAAO,IAAI;IACb;EACF,CAAC,CAAC,MAAM;IACN;EAAA;EAGF,OAAOH,SAAS,EAAEK,IAAI,KAAK,WAAW;AACxC,CAAC;AAED,OAAO,MAAMC,sBAAsB,GACjCA,CAAC;EAAEC,KAAK;EAAEC;AAA0C,CAAC,KACrD,CAAC;EAAEC,KAAK;EAAEC,UAAU;EAAEC;AAAsE,CAAC,KAAK;EAChG,SAAS;;EAET,IAAIF,KAAK,IAAI,CAAC,EAAE;IACd,OAAO;MACLC,UAAU;MACVC;IACF,CAAC;EACH;EAEA,MAAMC,aAAa,GAAG,CAACL,KAAK,GAAGE,KAAK,GAAGF,KAAK,IAAI,CAAC;EACjD,MAAMM,aAAa,GAAG,CAACL,MAAM,GAAGC,KAAK,GAAGD,MAAM,IAAI,CAAC;EAEnD,OAAO;IACLE,UAAU,EAAEI,IAAI,CAACC,GAAG,CAAC,CAACH,aAAa,EAAEE,IAAI,CAACE,GAAG,CAACJ,aAAa,EAAEF,UAAU,CAAC,CAAC;IACzEC,UAAU,EAAEG,IAAI,CAACC,GAAG,CAAC,CAACF,aAAa,EAAEC,IAAI,CAACE,GAAG,CAACH,aAAa,EAAEF,UAAU,CAAC;EAC1E,CAAC;AACH,CAAC","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"GestureViewer.d.ts","sourceRoot":"","sources":["../../../src/GestureViewer.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,QAAQ,EAAyE,MAAM,cAAc,CAAC;AAIpH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAKlD,wBAAgB,aAAa,CAAC,CAAC,GAAG,GAAG,EAAE,EAAE,GAAG,OAAO,QAAQ,EAAE,EAC3D,EAAc,EACd,IAAI,EACJ,UAAU,EAAE,cAAc,EAC1B,eAAe,EACf,aAAa,EACb,KAAK,EAAE,WAAW,EAClB,SAAS,EACT,aAAa,EAAE,kBAAkB,EACjC,cAAc,EACd,YAAgB,EAChB,WAAe,EACf,OAAe,EACf,GAAG,KAAK,EACT,EAAE,kBAAkB,CAAC,CAAC,EAAE,EAAE,CAAC,2CA+H3B"}
1
+ {"version":3,"file":"GestureViewer.d.ts","sourceRoot":"","sources":["../../../src/GestureViewer.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,QAAQ,EAAyE,MAAM,cAAc,CAAC;AAIpH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAKlD,wBAAgB,aAAa,CAAC,CAAC,GAAG,GAAG,EAAE,EAAE,GAAG,OAAO,QAAQ,EAAE,EAC3D,EAAc,EACd,IAAI,EACJ,UAAU,EAAE,cAAc,EAC1B,eAAe,EACf,aAAa,EACb,KAAK,EAAE,WAAW,EAClB,SAAS,EACT,aAAa,EAAE,kBAAkB,EACjC,cAAc,EACd,YAAgB,EAChB,WAAe,EACf,OAAe,EACf,GAAG,KAAK,EACT,EAAE,kBAAkB,CAAC,CAAC,EAAE,EAAE,CAAC,2CAuI3B"}
@@ -1,3 +1,4 @@
1
+ import { type SharedValue } from 'react-native-reanimated';
1
2
  export type GestureViewerManagerState = {
2
3
  currentIndex: number;
3
4
  dataLength: number;
@@ -6,9 +7,15 @@ declare class GestureViewerManager {
6
7
  private currentIndex;
7
8
  private dataLength;
8
9
  private width;
10
+ private height;
11
+ private scale;
12
+ private translateX;
13
+ private translateY;
14
+ private maxZoomScale;
9
15
  private listRef;
10
16
  private enableSwipeGesture;
11
17
  private listeners;
18
+ private rotation;
12
19
  private notifyListeners;
13
20
  subscribe(listener: (state: GestureViewerManagerState) => void): () => void;
14
21
  getState(): {
@@ -16,11 +23,46 @@ declare class GestureViewerManager {
16
23
  dataLength: number;
17
24
  };
18
25
  setWidth(width: number): void;
26
+ setHeight(height: number): void;
19
27
  setListRef(ref: any): void;
20
28
  setDataLength(length: number): void;
21
29
  setEnableSwipeGesture(enabled: boolean): void;
22
30
  setCurrentIndex(index: number): void;
31
+ setZoomSharedValues(scale: SharedValue<number>, translateX: SharedValue<number>, translateY: SharedValue<number>, maxZoomScale: number): void;
23
32
  notifyStateChange(): void;
33
+ setRotation(rotation: SharedValue<number>): void;
34
+ /**
35
+ * @param angle - The angle to rotate.
36
+ * @default 90 (0, 90, 180, 270, 360)
37
+ * @param clockwise - The direction to rotate.
38
+ * @default true (clockwise)
39
+ *
40
+ * @example
41
+ * rotate(0) // reset rotation
42
+ * rotate(number, false) // rotate {number} degrees counter-clockwise
43
+ * rotate(90) // rotate 90 degrees clockwise
44
+ * rotate(180) // rotate 180 degrees clockwise
45
+ * rotate(270) // rotate 270 degrees clockwise
46
+ * rotate(360) // rotate 360 degrees clockwise
47
+ */
48
+ rotate: (angle?: 0 | 90 | 180 | 270 | 360, clockwise?: boolean) => void;
49
+ /**
50
+ * @param multiplier - The multiplier to zoom in.
51
+ * @range 0.01 - 1
52
+ * @default 0.25
53
+ */
54
+ zoomIn: (multiplier?: number) => void;
55
+ /**
56
+ * @param multiplier - The multiplier to zoom out.
57
+ * @range 0.01 - 1
58
+ * @default 0.25
59
+ */
60
+ zoomOut: (multiplier?: number) => void;
61
+ /**
62
+ * @param scale - The scale to reset to.
63
+ * @default 1
64
+ */
65
+ resetZoom: (scale?: number) => void;
24
66
  goToIndex: (index: number) => void;
25
67
  goToPrevious: () => void;
26
68
  goToNext: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"GestureViewerManager.d.ts","sourceRoot":"","sources":["../../../src/GestureViewerManager.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,yBAAyB,GAAG;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,cAAM,oBAAoB;IACxB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,kBAAkB,CAAQ;IAClC,OAAO,CAAC,SAAS,CAAyD;IAO1E,OAAO,CAAC,eAAe;IAMvB,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,yBAAyB,KAAK,IAAI;IAQ9D,QAAQ;;;;IAOR,QAAQ,CAAC,KAAK,EAAE,MAAM;IAItB,UAAU,CAAC,GAAG,EAAE,GAAG;IAInB,aAAa,CAAC,MAAM,EAAE,MAAM;IAI5B,qBAAqB,CAAC,OAAO,EAAE,OAAO;IAItC,eAAe,CAAC,KAAK,EAAE,MAAM;IAM7B,iBAAiB;IAIjB,SAAS,GAAI,OAAO,MAAM,UAcxB;IAEF,YAAY,aAIV;IAEF,QAAQ,aAIN;IAEF,OAAO;CAOR;AAED,eAAe,oBAAoB,CAAC"}
1
+ {"version":3,"file":"GestureViewerManager.d.ts","sourceRoot":"","sources":["../../../src/GestureViewerManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAc,MAAM,yBAAyB,CAAC;AAGvE,MAAM,MAAM,yBAAyB,GAAG;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,cAAM,oBAAoB;IACxB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,kBAAkB,CAAQ;IAClC,OAAO,CAAC,SAAS,CAAyD;IAC1E,OAAO,CAAC,QAAQ,CAAoC;IAEpD,OAAO,CAAC,eAAe;IAMvB,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,yBAAyB,KAAK,IAAI;IAQ9D,QAAQ;;;;IAOR,QAAQ,CAAC,KAAK,EAAE,MAAM;IAItB,SAAS,CAAC,MAAM,EAAE,MAAM;IAIxB,UAAU,CAAC,GAAG,EAAE,GAAG;IAInB,aAAa,CAAC,MAAM,EAAE,MAAM;IAI5B,qBAAqB,CAAC,OAAO,EAAE,OAAO;IAItC,eAAe,CAAC,KAAK,EAAE,MAAM;IAM7B,mBAAmB,CACjB,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,EAC1B,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,EAC/B,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,EAC/B,YAAY,EAAE,MAAM;IAQtB,iBAAiB;IAIjB,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC;IAIzC;;;;;;;;;;;;;OAaG;IACH,MAAM,GAAI,QAAO,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAQ,EAAE,mBAAgB,UA2B9D;IAEF;;;;OAIG;IACH,MAAM,GAAI,mBAAiB,UAoBzB;IAEF;;;;OAIG;IACH,OAAO,GAAI,mBAAiB,UA0B1B;IAEF;;;OAGG;IACH,SAAS,GAAI,cAAS,UAQpB;IAEF,SAAS,GAAI,OAAO,MAAM,UAcxB;IAEF,YAAY,aAIV;IAEF,QAAQ,aAIN;IAEF,OAAO;CAaR;AAED,eAAe,oBAAoB,CAAC"}
@@ -7,6 +7,7 @@ export declare const useGestureViewer: <T = any>({ data, initialIndex, onIndexCh
7
7
  translateY: import("react-native-reanimated").SharedValue<number>;
8
8
  listRef: import("react").RefObject<any>;
9
9
  isZoomed: boolean;
10
+ isRotated: boolean;
10
11
  dismissGesture: import("react-native-gesture-handler/lib/typescript/handlers/gestures/panGesture").PanGesture;
11
12
  zoomGesture: import("react-native-gesture-handler/lib/typescript/handlers/gestures/gestureComposition").ComposedGesture;
12
13
  onMomentumScrollEnd: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
@@ -15,14 +16,22 @@ export declare const useGestureViewer: <T = any>({ data, initialIndex, onIndexCh
15
16
  translateY: number;
16
17
  translateX?: undefined;
17
18
  scale?: undefined;
19
+ rotate?: undefined;
18
20
  } | {
19
21
  translateX: number;
20
22
  translateY?: undefined;
21
23
  scale?: undefined;
24
+ rotate?: undefined;
22
25
  } | {
23
26
  scale: number;
24
27
  translateY?: undefined;
25
28
  translateX?: undefined;
29
+ rotate?: undefined;
30
+ } | {
31
+ rotate: string;
32
+ translateY?: undefined;
33
+ translateX?: undefined;
34
+ scale?: undefined;
26
35
  })[];
27
36
  };
28
37
  backdropStyle: {
@@ -1 +1 @@
1
- {"version":3,"file":"useGestureViewer.d.ts","sourceRoot":"","sources":["../../../src/useGestureViewer.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAE1B,MAAM,cAAc,CAAC;AActB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD,KAAK,qBAAqB,CAAC,CAAC,GAAG,GAAG,IAAI,IAAI,CACxC,kBAAkB,CAAC,CAAC,CAAC,EACrB,YAAY,GAAG,iBAAiB,GAAG,eAAe,GAAG,WAAW,GAAG,gBAAgB,GAAG,eAAe,CACtG,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,CAAC,GAAG,GAAG,EAAE,yQAoBvC,qBAAqB,CAAC,CAAC,CAAC;;;;;;;;iCAqIf,oBAAoB,CAAC,iBAAiB,CAAC;;;;;;;;;;;;;;;;;;;CAmPlD,CAAC"}
1
+ {"version":3,"file":"useGestureViewer.d.ts","sourceRoot":"","sources":["../../../src/useGestureViewer.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAE1B,MAAM,cAAc,CAAC;AActB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAGlD,KAAK,qBAAqB,CAAC,CAAC,GAAG,GAAG,IAAI,IAAI,CACxC,kBAAkB,CAAC,CAAC,CAAC,EACrB,YAAY,GAAG,iBAAiB,GAAG,eAAe,GAAG,WAAW,GAAG,gBAAgB,GAAG,eAAe,CACtG,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,CAAC,GAAG,GAAG,EAAE,yQAoBvC,qBAAqB,CAAC,CAAC,CAAC;;;;;;;;;iCA8If,oBAAoB,CAAC,iBAAiB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4QlD,CAAC"}
@@ -2,6 +2,10 @@ export declare const useGestureViewerController: (id?: string) => {
2
2
  goToIndex: (index: number) => void;
3
3
  goToPrevious: () => void;
4
4
  goToNext: () => void;
5
+ zoomIn: (multiplier?: number) => void;
6
+ zoomOut: (multiplier?: number) => void;
7
+ resetZoom: (scale?: number) => void;
8
+ rotate: (angle?: 0 | 90 | 180 | 270 | 360, clockwise?: boolean) => void;
5
9
  currentIndex: number;
6
10
  totalCount: number;
7
11
  };
@@ -1 +1 @@
1
- {"version":3,"file":"useGestureViewerController.d.ts","sourceRoot":"","sources":["../../../src/useGestureViewerController.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,0BAA0B,GAAI,WAAc;;;;;;CA0CxD,CAAC"}
1
+ {"version":3,"file":"useGestureViewerController.d.ts","sourceRoot":"","sources":["../../../src/useGestureViewerController.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,0BAA0B,GAAI,WAAc;;;;;;;;;;CA8CxD,CAAC"}
@@ -2,4 +2,15 @@ import type { FlatListComponent, ScrollViewComponent } from './types';
2
2
  export declare const isScrollViewLike: (component: any) => component is ScrollViewComponent;
3
3
  export declare const isFlatListLike: (component: any) => component is FlatListComponent;
4
4
  export declare const isFlashListLike: (component: any) => component is any;
5
+ export declare const createBoundsConstraint: ({ width, height }: {
6
+ width: number;
7
+ height: number;
8
+ }) => ({ scale, translateX, translateY }: {
9
+ translateX: number;
10
+ translateY: number;
11
+ scale: number;
12
+ }) => {
13
+ translateX: number;
14
+ translateY: number;
15
+ };
5
16
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEtE,eAAO,MAAM,gBAAgB,GAAI,WAAW,GAAG,KAAG,SAAS,IAAI,mBAE9D,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,WAAW,GAAG,KAAG,SAAS,IAAI,iBAM5D,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,WAAW,GAAG,KAAG,SAAS,IAAI,GAY7D,CAAC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEtE,eAAO,MAAM,gBAAgB,GAAI,WAAW,GAAG,KAAG,SAAS,IAAI,mBAE9D,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,WAAW,GAAG,KAAG,SAAS,IAAI,iBAM5D,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,WAAW,GAAG,KAAG,SAAS,IAAI,GAY7D,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAChC,mBAAmB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,MACpD,mCAAmC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;;;CAiB5F,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-gesture-image-viewer",
3
- "version": "1.2.3",
3
+ "version": "1.4.0",
4
4
  "description": "🖼️ A highly customizable and easy-to-use React Native image viewer with gesture support and external controls",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -29,16 +29,24 @@ export function GestureViewer<T = any, LC = typeof FlatList>({
29
29
 
30
30
  const width = useSnap ? customWidth || screenWidth : screenWidth;
31
31
 
32
- const { listRef, isZoomed, dismissGesture, zoomGesture, onMomentumScrollEnd, animatedStyle, backdropStyle } =
33
- useGestureViewer({
34
- id,
35
- data,
36
- width,
37
- initialIndex,
38
- itemSpacing,
39
- useSnap,
40
- ...props,
41
- });
32
+ const {
33
+ listRef,
34
+ isZoomed,
35
+ isRotated,
36
+ dismissGesture,
37
+ zoomGesture,
38
+ onMomentumScrollEnd,
39
+ animatedStyle,
40
+ backdropStyle,
41
+ } = useGestureViewer({
42
+ id,
43
+ data,
44
+ width,
45
+ initialIndex,
46
+ itemSpacing,
47
+ useSnap,
48
+ ...props,
49
+ });
42
50
 
43
51
  const renderItem = useCallback(
44
52
  ({ item, index }: { item: T; index: number }) => {
@@ -89,7 +97,7 @@ export function GestureViewer<T = any, LC = typeof FlatList>({
89
97
  const commonProps: ScrollViewProps = useMemo(
90
98
  () => ({
91
99
  horizontal: true,
92
- scrollEnabled: !isZoomed,
100
+ scrollEnabled: !isZoomed && !isRotated,
93
101
  showsHorizontalScrollIndicator: false,
94
102
  onMomentumScrollEnd: onMomentumScrollEnd,
95
103
  ...(useSnap
@@ -104,7 +112,7 @@ export function GestureViewer<T = any, LC = typeof FlatList>({
104
112
  scrollEventThrottle: 16,
105
113
  removeClippedSubviews: true,
106
114
  }),
107
- [width, itemSpacing, isZoomed, onMomentumScrollEnd, useSnap],
115
+ [width, itemSpacing, isZoomed, isRotated, onMomentumScrollEnd, useSnap],
108
116
  );
109
117
 
110
118
  const listComponent = (
@@ -1,3 +1,6 @@
1
+ import { type SharedValue, withTiming } from 'react-native-reanimated';
2
+ import { createBoundsConstraint } from './utils';
3
+
1
4
  export type GestureViewerManagerState = {
2
5
  currentIndex: number;
3
6
  dataLength: number;
@@ -7,14 +10,15 @@ class GestureViewerManager {
7
10
  private currentIndex = 0;
8
11
  private dataLength = 0;
9
12
  private width = 0;
13
+ private height = 0;
14
+ private scale: SharedValue<number> | null = null;
15
+ private translateX: SharedValue<number> | null = null;
16
+ private translateY: SharedValue<number> | null = null;
17
+ private maxZoomScale = 2;
10
18
  private listRef: any | null = null;
11
19
  private enableSwipeGesture = true;
12
20
  private listeners = new Set<(state: GestureViewerManagerState) => void>();
13
-
14
- // private updateState(newState: Partial<any>) {
15
- // Object.assign(this, newState);
16
- // this.notifyListeners();
17
- // }
21
+ private rotation: SharedValue<number> | null = null;
18
22
 
19
23
  private notifyListeners() {
20
24
  const state = this.getState();
@@ -41,6 +45,10 @@ class GestureViewerManager {
41
45
  this.width = width;
42
46
  }
43
47
 
48
+ setHeight(height: number) {
49
+ this.height = height;
50
+ }
51
+
44
52
  setListRef(ref: any) {
45
53
  this.listRef = ref;
46
54
  }
@@ -59,10 +67,143 @@ class GestureViewerManager {
59
67
  }
60
68
  }
61
69
 
70
+ setZoomSharedValues(
71
+ scale: SharedValue<number>,
72
+ translateX: SharedValue<number>,
73
+ translateY: SharedValue<number>,
74
+ maxZoomScale: number,
75
+ ) {
76
+ this.scale = scale;
77
+ this.translateX = translateX;
78
+ this.translateY = translateY;
79
+ this.maxZoomScale = maxZoomScale;
80
+ }
81
+
62
82
  notifyStateChange() {
63
83
  this.notifyListeners();
64
84
  }
65
85
 
86
+ setRotation(rotation: SharedValue<number>) {
87
+ this.rotation = rotation;
88
+ }
89
+
90
+ /**
91
+ * @param angle - The angle to rotate.
92
+ * @default 90 (0, 90, 180, 270, 360)
93
+ * @param clockwise - The direction to rotate.
94
+ * @default true (clockwise)
95
+ *
96
+ * @example
97
+ * rotate(0) // reset rotation
98
+ * rotate(number, false) // rotate {number} degrees counter-clockwise
99
+ * rotate(90) // rotate 90 degrees clockwise
100
+ * rotate(180) // rotate 180 degrees clockwise
101
+ * rotate(270) // rotate 270 degrees clockwise
102
+ * rotate(360) // rotate 360 degrees clockwise
103
+ */
104
+ rotate = (angle: 0 | 90 | 180 | 270 | 360 = 90, clockwise = true) => {
105
+ const MAX_ANGLE = 360;
106
+
107
+ if (
108
+ !this.rotation ||
109
+ angle < 0 ||
110
+ angle > MAX_ANGLE ||
111
+ (angle !== 0 && this.rotation.value % angle !== 0 && angle !== 360)
112
+ ) {
113
+ return;
114
+ }
115
+
116
+ if (angle === 0) {
117
+ const nextAngle = Math.floor(this.rotation.value / MAX_ANGLE) * MAX_ANGLE;
118
+
119
+ this.rotation.value = withTiming(clockwise ? nextAngle : nextAngle - MAX_ANGLE);
120
+ return;
121
+ }
122
+
123
+ if (angle === 360) {
124
+ this.rotation.value = withTiming(clockwise ? this.rotation.value + MAX_ANGLE : this.rotation.value - MAX_ANGLE);
125
+ return;
126
+ }
127
+
128
+ const nextAngle = clockwise ? this.rotation.value + angle : this.rotation.value - angle;
129
+
130
+ this.rotation.value = withTiming(nextAngle);
131
+ };
132
+
133
+ /**
134
+ * @param multiplier - The multiplier to zoom in.
135
+ * @range 0.01 - 1
136
+ * @default 0.25
137
+ */
138
+ zoomIn = (multiplier = 0.25) => {
139
+ if (!this.scale || !this.translateX || !this.translateY || multiplier < 0.01 || multiplier > 1) {
140
+ return;
141
+ }
142
+
143
+ const nextScale = Math.min(this.scale.value * (1 + multiplier), this.maxZoomScale);
144
+
145
+ this.scale.value = withTiming(nextScale);
146
+
147
+ const { translateX, translateY } = createBoundsConstraint({
148
+ width: this.width,
149
+ height: this.height,
150
+ })({
151
+ translateX: this.translateX.value,
152
+ translateY: this.translateY.value,
153
+ scale: nextScale,
154
+ });
155
+
156
+ this.translateX.value = withTiming(translateX);
157
+ this.translateY.value = withTiming(translateY);
158
+ };
159
+
160
+ /**
161
+ * @param multiplier - The multiplier to zoom out.
162
+ * @range 0.01 - 1
163
+ * @default 0.25
164
+ */
165
+ zoomOut = (multiplier = 0.25) => {
166
+ if (!this.scale || !this.translateX || !this.translateY || multiplier < 0.01 || multiplier > 1) {
167
+ return;
168
+ }
169
+
170
+ const nextScale = Math.max(this.scale.value / (1 + multiplier), 1);
171
+
172
+ this.scale.value = withTiming(nextScale);
173
+
174
+ if (nextScale === 1) {
175
+ this.translateX.value = withTiming(0);
176
+ this.translateY.value = withTiming(0);
177
+ return;
178
+ }
179
+
180
+ const { translateX, translateY } = createBoundsConstraint({
181
+ width: this.width,
182
+ height: this.height,
183
+ })({
184
+ translateX: this.translateX.value,
185
+ translateY: this.translateY.value,
186
+ scale: nextScale,
187
+ });
188
+
189
+ this.translateX.value = withTiming(translateX);
190
+ this.translateY.value = withTiming(translateY);
191
+ };
192
+
193
+ /**
194
+ * @param scale - The scale to reset to.
195
+ * @default 1
196
+ */
197
+ resetZoom = (scale = 1) => {
198
+ if (!this.scale || !this.translateX || !this.translateY || scale <= 0 || scale > this.maxZoomScale) {
199
+ return;
200
+ }
201
+
202
+ this.scale.value = withTiming(scale);
203
+ this.translateX.value = withTiming(0);
204
+ this.translateY.value = withTiming(0);
205
+ };
206
+
66
207
  goToIndex = (index: number) => {
67
208
  if (index < 0 || index >= this.dataLength || !this.enableSwipeGesture || !this.listRef) {
68
209
  return;
@@ -97,6 +238,12 @@ class GestureViewerManager {
97
238
  this.enableSwipeGesture = true;
98
239
  this.currentIndex = 0;
99
240
  this.dataLength = 0;
241
+
242
+ this.maxZoomScale = 2;
243
+ this.scale = null;
244
+ this.translateX = null;
245
+ this.translateY = null;
246
+ this.rotation = null;
100
247
  }
101
248
  }
102
249