Skip to content

Commit dc9270f

Browse files
authored
feat: add GestureViewerController types and enhance TSDoc documentation (#43)
- Add GestureViewerController type definition - Mark state properties as readonly for immutability - Enhance TSDoc with comprehensive parameter descriptions and examples - Improve useGestureViewerController hook docs for destructuring usage
1 parent 6cf7d01 commit dc9270f

File tree

5 files changed

+226
-58
lines changed

5 files changed

+226
-58
lines changed

.changeset/brown-ways-share.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
"react-native-gesture-image-viewer": patch
3+
---
4+
5+
feat: add GestureViewerController types and enhance TSDoc documentation
6+
7+
- Add GestureViewerController type definition
8+
- Mark state properties as readonly for immutability
9+
- Enhance TSDoc with comprehensive parameter descriptions and examples
10+
- Improve useGestureViewerController hook docs for destructuring usage

src/GestureViewerManager.ts

Lines changed: 4 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
import { type SharedValue, withTiming } from 'react-native-reanimated';
2+
import type { GestureViewerControllerState } from './types';
23
import { createBoundsConstraint } from './utils';
34

4-
export type GestureViewerManagerState = {
5-
currentIndex: number;
6-
dataLength: number;
7-
};
8-
95
class GestureViewerManager {
106
private currentIndex = 0;
117
private dataLength = 0;
@@ -17,7 +13,7 @@ class GestureViewerManager {
1713
private maxZoomScale = 2;
1814
private listRef: any | null = null;
1915
private enableSwipeGesture = true;
20-
private listeners = new Set<(state: GestureViewerManagerState) => void>();
16+
private listeners = new Set<(state: GestureViewerControllerState) => void>();
2117
private rotation: SharedValue<number> | null = null;
2218

2319
private notifyListeners() {
@@ -26,7 +22,7 @@ class GestureViewerManager {
2622
this.listeners.forEach((listener) => listener(state));
2723
}
2824

29-
subscribe(listener: (state: GestureViewerManagerState) => void) {
25+
subscribe(listener: (state: GestureViewerControllerState) => void) {
3026
this.listeners.add(listener);
3127

3228
return () => {
@@ -37,7 +33,7 @@ class GestureViewerManager {
3733
getState() {
3834
return {
3935
currentIndex: this.currentIndex,
40-
dataLength: this.dataLength,
36+
totalCount: this.dataLength,
4137
};
4238
}
4339

@@ -87,20 +83,6 @@ class GestureViewerManager {
8783
this.rotation = rotation;
8884
}
8985

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-
*/
10486
rotate = (angle: 0 | 90 | 180 | 270 | 360 = 90, clockwise = true) => {
10587
const MAX_ANGLE = 360;
10688

@@ -130,11 +112,6 @@ class GestureViewerManager {
130112
this.rotation.value = withTiming(nextAngle);
131113
};
132114

133-
/**
134-
* @param multiplier - The multiplier to zoom in.
135-
* @range 0.01 - 1
136-
* @default 0.25
137-
*/
138115
zoomIn = (multiplier = 0.25) => {
139116
if (!this.scale || !this.translateX || !this.translateY || multiplier < 0.01 || multiplier > 1) {
140117
return;
@@ -157,11 +134,6 @@ class GestureViewerManager {
157134
this.translateY.value = withTiming(translateY);
158135
};
159136

160-
/**
161-
* @param multiplier - The multiplier to zoom out.
162-
* @range 0.01 - 1
163-
* @default 0.25
164-
*/
165137
zoomOut = (multiplier = 0.25) => {
166138
if (!this.scale || !this.translateX || !this.translateY || multiplier < 0.01 || multiplier > 1) {
167139
return;
@@ -190,10 +162,6 @@ class GestureViewerManager {
190162
this.translateY.value = withTiming(translateY);
191163
};
192164

193-
/**
194-
* @param scale - The scale to reset to.
195-
* @default 1
196-
*/
197165
resetZoom = (scale = 1) => {
198166
if (!this.scale || !this.translateX || !this.translateY || scale <= 0 || scale > this.maxZoomScale) {
199167
return;

src/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
export { GestureViewer } from './GestureViewer';
2-
export type { GestureViewerProps } from './types';
2+
export type { GestureViewerController, GestureViewerProps } from './types';
33
export { useGestureViewerController } from './useGestureViewerController';

src/types.ts

Lines changed: 153 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export interface GestureViewerProps<T = any, LC = typeof RNFlatList> {
1717
/**
1818
* When you want to efficiently manage multiple `GestureViewer` instances, you can use the `id` prop to use multiple `GestureViewer` components.
1919
* @remark `GestureViewer` automatically removes instances from memory when components are unmounted, so no manual memory management is required.
20-
* @default 'default'
20+
* @defaultValue 'default'
2121
*/
2222
id?: string;
2323
/**
@@ -26,7 +26,7 @@ export interface GestureViewerProps<T = any, LC = typeof RNFlatList> {
2626
data: T[];
2727
/**
2828
* The index of the item to display in the `GestureViewer` when the component is mounted.
29-
* @default 0
29+
* @defaultValue 0
3030
*/
3131
initialIndex?: number;
3232
/**
@@ -52,7 +52,7 @@ export interface GestureViewerProps<T = any, LC = typeof RNFlatList> {
5252
/**
5353
* The width of the `GestureViewer`.
5454
* @remark If you don't set this prop, the width of the `GestureViewer` will be the same as the width of the screen.
55-
* @default screen width
55+
* @defaultValue screen width
5656
*/
5757
width?: number;
5858
/**
@@ -65,32 +65,32 @@ export interface GestureViewerProps<T = any, LC = typeof RNFlatList> {
6565
* **`true`**: Snap mode (`snapToInterval` auto-calculated)
6666
* - `snapToInterval` is automatically calculated based on `width` and `itemSpacing` values
6767
* - Use this option when you need item spacing
68-
* @default false
68+
* @defaultValue false
6969
*
7070
*/
7171
useSnap?: boolean;
7272
/**
7373
* `dismissThreshold` controls when `onDismiss` is called by applying a threshold value during vertical gestures.
74-
* @default 80
74+
* @defaultValue 80
7575
*/
7676
dismissThreshold?: number;
7777
// swipeThreshold?: number;
7878
// velocityThreshold?: number;
7979
/**
8080
* Calls `onDismiss` function when swiping down.
8181
* @remark Useful for closing modals with downward swipe gestures.
82-
* @default true
82+
* @defaultValue true
8383
*/
8484
enableDismissGesture?: boolean;
8585
/**
8686
* Controls left/right swipe gestures.
8787
* @remark When `false`, horizontal gestures are disabled.
88-
* @default true
88+
* @defaultValue true
8989
*/
9090
enableSwipeGesture?: boolean;
9191
/**
9292
* `resistance` controls the range of vertical movement by applying resistance during vertical gestures.
93-
* @default 2
93+
* @defaultValue 2
9494
*/
9595
resistance?: number;
9696
/**
@@ -109,36 +109,175 @@ export interface GestureViewerProps<T = any, LC = typeof RNFlatList> {
109109
/**
110110
* By default, the background `opacity` gradually decreases from 1 to 0 during downward swipe gestures.
111111
* @remark When `false`, this animation is disabled.
112-
* @default true
112+
* @defaultValue true
113113
*/
114114
animateBackdrop?: boolean;
115115
/**
116116
* Only works when zoom is active, allows moving item position when zoomed.
117117
* @remark When `false`, gesture movement is disabled during zoom.
118-
* @default true
118+
* @defaultValue true
119119
*/
120120
enableZoomPanGesture?: boolean;
121121
/**
122122
* Controls two-finger pinch gestures.
123123
* @remark When `false`, two-finger zoom gestures are disabled.
124-
* @default true
124+
* @defaultValue true
125125
*/
126126
enableZoomGesture?: boolean;
127127
/**
128128
* Controls double-tap zoom gestures.
129129
* @remark When `false`, double-tap zoom gestures are disabled.
130-
* @default true
130+
* @defaultValue true
131131
*/
132132
enableDoubleTapGesture?: boolean;
133133
/**
134134
* The maximum zoom scale.
135-
* @default 2
135+
* @defaultValue 2
136136
*/
137137
maxZoomScale?: number;
138138
/**
139139
* The spacing between items in pixels.
140140
* @remark Only applied when `useSnap` is `true`.
141-
* @default 0
141+
* @defaultValue 0
142142
*/
143143
itemSpacing?: number;
144144
}
145+
146+
/**
147+
* Supported rotation angles in degrees.
148+
*/
149+
export type RotationAngle = 0 | 90 | 180 | 270 | 360;
150+
151+
/**
152+
* Controller for managing gesture-based image/content viewer interactions.
153+
* Provides navigation, zoom, and rotation capabilities with state management.
154+
*/
155+
export type GestureViewerController = {
156+
/**
157+
* Navigates to the specified index in the viewer.
158+
* Updates the currentIndex in the controller state.
159+
*
160+
* @param index - The target index (must be between 0 and totalCount - 1)
161+
* @throws Will throw an error if index is out of bounds
162+
*
163+
* @example
164+
* ```typescript
165+
* controller.goToIndex(0); // Go to first item
166+
* controller.goToIndex(controller.totalCount - 1); // Go to last item
167+
* ```
168+
*/
169+
goToIndex: (index: number) => void;
170+
171+
/**
172+
* Navigates to the previous item in the sequence.
173+
* If already at the first item, behavior depends on implementation (may wrap or do nothing).
174+
* Updates currentIndex in the controller state.
175+
*/
176+
goToPrevious: () => void;
177+
178+
/**
179+
* Navigates to the next item in the sequence.
180+
* If already at the last item, behavior depends on implementation (may wrap or do nothing).
181+
* Updates currentIndex in the controller state.
182+
*/
183+
goToNext: () => void;
184+
185+
/**
186+
* Zooms in by the specified multiplier.
187+
*
188+
* @param multiplier - The zoom multiplier (0.01 - 1.0). Higher values zoom in more.
189+
* @defaultValue 0.25
190+
*
191+
* @example
192+
* ```typescript
193+
* controller.zoomIn(); // Zoom in by 25%
194+
* controller.zoomIn(0.5); // Zoom in by 50%
195+
* ```
196+
*/
197+
zoomIn: (multiplier?: number) => void;
198+
199+
/**
200+
* Zooms out by the specified multiplier.
201+
*
202+
* @param multiplier - The zoom multiplier (0.01 - 1.0). Higher values zoom out more.
203+
* @defaultValue 0.25
204+
*
205+
* @example
206+
* ```typescript
207+
* controller.zoomOut(); // Zoom out by 25%
208+
* controller.zoomOut(0.1); // Zoom out by 10%
209+
* ```
210+
*/
211+
zoomOut: (multiplier?: number) => void;
212+
213+
/**
214+
* Resets the zoom level to the specified scale.
215+
*
216+
* @param scale - The scale to reset to (1.0 = original size)
217+
* @defaultValue 1.0
218+
*
219+
* @example
220+
* ```typescript
221+
* controller.resetZoom(); // Reset to original size
222+
* controller.resetZoom(0.5); // Reset to 50% of original size
223+
* ```
224+
*/
225+
resetZoom: (scale?: number) => void;
226+
227+
/**
228+
* Rotates the content by the specified angle.
229+
*
230+
* @param angle - Rotation angle in degrees. Must be one of: 0, 90, 180, 270, 360
231+
* @param clockwise - Direction of rotation when angle is not 0 or 360
232+
* @defaultValue angle: `90`, clockwise: `true`
233+
*
234+
* @remarks
235+
* - Angle 0 or 360 resets rotation regardless of clockwise parameter
236+
* - The clockwise parameter only affects rotation when angle is 90, 180, or 270
237+
* - Rotation is cumulative and affects the current orientation
238+
*
239+
* @example
240+
* ```typescript
241+
* controller.rotate(); // Rotate 90 degrees clockwise
242+
* controller.rotate(0); // Reset rotation
243+
* controller.rotate(90, false); // Rotate 90 degrees counter-clockwise
244+
* controller.rotate(180); // Rotate 180 degrees (clockwise by default)
245+
* controller.rotate(270, false); // Rotate 270 degrees counter-clockwise
246+
* controller.rotate(360); // Reset rotation (same as 0)
247+
* ```
248+
*/
249+
rotate: (angle?: RotationAngle, clockwise?: boolean) => void;
250+
} & GestureViewerControllerState;
251+
252+
/**
253+
* State information for the gesture viewer controller.
254+
* Contains read-only properties that reflect the current state.
255+
*/
256+
export type GestureViewerControllerState = {
257+
/**
258+
* The current index of the active item in the viewer.
259+
*
260+
* @remarks
261+
* This value is automatically updated when navigation methods are called.
262+
*
263+
* @example
264+
* ```typescript
265+
* console.log(`Currently viewing item ${controller.currentIndex + 1} of ${controller.totalCount}`);
266+
* ```
267+
*/
268+
readonly currentIndex: number;
269+
270+
/**
271+
* The total number of items available in the viewer.
272+
*
273+
* @remarks
274+
* This value determines the valid range for currentIndex (0 to totalCount - 1).
275+
*
276+
* @example
277+
* ```typescript
278+
* const hasNext = controller.currentIndex < controller.totalCount - 1;
279+
* const hasPrevious = controller.currentIndex > 0;
280+
* ```
281+
*/
282+
readonly totalCount: number;
283+
};

0 commit comments

Comments
 (0)