{"id":13632573,"url":"https://github.com/terrysahaidak/react-native-gallery-toolkit","last_synced_at":"2025-04-04T16:15:12.618Z","repository":{"id":38425633,"uuid":"267674855","full_name":"terrysahaidak/react-native-gallery-toolkit","owner":"terrysahaidak","description":"Reanimated 2 powered gallery implementation","archived":false,"fork":false,"pushed_at":"2023-03-06T13:46:41.000Z","size":37841,"stargazers_count":657,"open_issues_count":33,"forks_count":37,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-03-28T15:07:47.734Z","etag":null,"topics":["android","animations","gallery","imageviewer","ios","lightbox","pager","pinch-to-zoom","react","react-native","reanimated","reanimated2"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/terrysahaidak.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2020-05-28T19:11:34.000Z","updated_at":"2025-01-27T21:24:59.000Z","dependencies_parsed_at":"2022-07-14T03:50:41.312Z","dependency_job_id":"520321d5-8225-461b-aa75-5ba68857d013","html_url":"https://github.com/terrysahaidak/react-native-gallery-toolkit","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terrysahaidak%2Freact-native-gallery-toolkit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terrysahaidak%2Freact-native-gallery-toolkit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terrysahaidak%2Freact-native-gallery-toolkit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/terrysahaidak%2Freact-native-gallery-toolkit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/terrysahaidak","download_url":"https://codeload.github.com/terrysahaidak/react-native-gallery-toolkit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247208151,"owners_count":20901570,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","animations","gallery","imageviewer","ios","lightbox","pager","pinch-to-zoom","react","react-native","reanimated","reanimated2"],"created_at":"2024-08-01T22:03:07.310Z","updated_at":"2025-04-04T16:15:12.598Z","avatar_url":"https://github.com/terrysahaidak.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ch1 align=\"center\"\u003eReact Native Gallery Toolkit\u003c/h1\u003e\n  \u003ch3 align=\"center\"\u003e Reanimated 2 and Gesturer Handler powered Gallery implementation\u003c/h3\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"200\" height=\"400\" src=\"gifs/promo.gif\" alt=\"Gallery in action gif\"\u003e\n  \u003cimg width=\"200\" height=\"400\" src=\"gifs/promo_2.gif\" alt=\"Instagram feed clone\"\u003e\n\u003c/p\u003e\n\n[![npm](https://img.shields.io/npm/v/react-native-gallery-toolkit.svg?style=plastic)](https://npmjs.com/package/react-native-gallery-toolkit)\n\n- [Installation](#installation)\n- [Standalone gallery](#standalone-gallery)\n  - [Limitations](#limitations)\n  - [Base props](#base-props)\n  - [Advance props](#advance-props)\n  - [Handlers](#handlers)\n  - [Methods](#methods)\n- [Pager](#pager)\n- [Transformer](#transformer)\n- [Scalable Image](#scalable-image)\n- [Examples](#examples)\n  - [Running on iOS](#running-on-ios)\n  - [Running on Android](#running-on-android)\n- [TODOs](#todos)\n- [LICENSE](#license)\n\n**Important!**\n\nThe library uses Reanimated 2 alpha. It means that it may be unstable.\nAlso, the library itself is in the alpha testing stage and may contain bugs.\n\n## Installation\n\nUse npm or yarn to install the library\n\n```bash\nnpm i --save react-native-gallery-toolkit\n```\n\n\u003e Also, you need to install [react-native-reanimated@2.0.0-alpha.7](https://github.com/software-mansion/react-native-reanimated) (the new 2 version) and [react-native-gesture-handler](https://github.com/software-mansion/react-native-gesture-handler), and follow their installation instructions.\n\nExpo is supported since SDK 40. \n\n```bash\nnpm install react-native-reanimated@2.0.0-rc.0\n```\n\n\u003e More information is available [https://docs.expo.io/versions/latest/sdk/reanimated/](here)\n\n\n## Standalone gallery\n\nStandalone gallery renders Pager which supports thousands of images thanks to virtualization. Each page renders ImageTransformer component which gives ability to pinch-to-zoom, double tap to zoom, also you can run custom callbacks and worklets on on tab, double tap, pan.\n\n```tsx\nimport {\n  StandaloneGallery,\n  GalleryItemType,\n  StandaloneGalleryHandler,\n} from 'react-native-gallery-toolkit';\n\nconst images: GalleryItemType[] = [\n  {\n    id: '1',\n    width: 300,\n    height: 300,\n    uri: 'https://placekitten.com/300/300',\n  },\n  {\n    id: '2',\n    width: 400,\n    height: 200,\n    uri: 'https://placekitten.com/400/200',\n  },\n];\n\nexport default function App() {\n  return \u003cStandaloneGallery items={images} /\u003e;\n}\n\n```\n\nSee [Full featured example](./Example/src/Standalone/FullFeatured.tsx) for example of usage of all the props.\n\n### Limitations\n\n- Only portrait orientation currently supported\n- There is no way to change dimensions without full re-render of the gallery\n- Debugging is not supported because of Reanimated v2 uses TurboModules. Use flipper to debug your JS Context.\n- On Android tap on hold on the screen while page changes doesn't trigger animation to stop due to bug in Gesture Handler.\n\n### Base props\n\nProp | Description | Type | Default\n------ | ------ | -------- | ------\n`items` | The array of items to render. But can also accept Map, Set, or Object with keys. If the type is not array, then `getTotalCount` and `getItem` should be defined too. | `Array\u003c{ width: number, height: number, id: string, uri: string  }\u003e` | `undefined`\n`width?` | Viewport width | `number` | `Dimensions.get('window').width`\n`height?` | Viewport height | `number` | `Dimensions.get('window').height`\n`numToRender?` | How many pages should be rendered at the same time | `number` | 2\n`gutterWidth?` | The width of the gutter between pages | `number` | 0\n`initialIndex?` | The initial page index | `number` | 0\n`keyExtractor?` | Callback which extract the key of the page. Receives current item of the provided `items` as well as current index | `(item: T, index: number) =\u003e string` | Uses index as a key by default\n\n### Advance props\n\nProp | Description | Type | Default\n------ | ------ | ------ | ------\n`getTotalCount?` | If the type of `items` is not an array, then this method should be defined to provide the total count of items | `(data: T) =\u003e number` | Required when `items` is not an array\n`getItem?` | If the type of `items` is not an array, then this method should be defined to provide the current item based on the index. Can return either the `item` or `undefined`. | `(data: T, index: number) =\u003e ItemT or undefined` | Required when `items` is not an array\n`renderImage?` | Callback that can be used to render custom image component. As an example, it can be used to render custom loading/error states | `(props: RenderImageProps, item: ItemT, index: number) =\u003e JSX.Element` | `() =\u003e Image`\n`renderPage?` | Callback that can be used to render custom page. Can be used to display some non-image pages such as Video, for instance | `(props: ImageRendererProps\u003cT\u003e, index: number) =\u003e JSX.Element` | `ImageTransformer`\n\n### Handlers\n\nProp | Description | Type | Is worklet? | Default\n------ | ------ | ------ | ------ | ------\n`onIndexChange?` | Fires when active index changes | `(nextIndex: number) =\u003e void`  | `Function` or `Worklet` | `undefined`\n`onTap?` | Executes when tap image transformer receives tap | `() =\u003e void` | `Function` or `Worklet` | `undefined`\n`onDoubleTap?` | Executes when tap image transformer receives double-tap  | `() =\u003e void` | `Function` or `Worklet` | `undefined`\n`onInteraction?` | Is called when either pan or scale has happened. | `(type: 'scale' or 'pan') =\u003e void` | `Function` or `Worklet` | `undefined`\n`onPagerTranslateChange?` | Executes on pager's horizontal pan | `(translateX: number) =\u003e void` | `Function` or `Worklet` | `undefined`\n`onGesture?` | Executes on pager's gesture | `(event: PanGestureHandlerGestureEvent, isActive: SharedValue\u003cboolean\u003e) =\u003e void` | `Function` or `Worklet` | `undefined`\n`shouldPagerHandleGestureEvent?` | Worklet that will be passed to pager's `shouldHandleEvent` to determine should pager handle this event. Can be used to handle \"swipe down to close\".  | `(event: PanGestureHandlerGestureEvent) =\u003e boolean` | Only `Worklet` | `undefined`\n\n### Methods\n\nName | Description | Type\n------ | ------ | ------\n`goNext` | Changes the active index forward | `() =\u003e void`\n`goBack` | Changes the active index backward | `() =\u003e void`\n`setIndex` | Sets the active index | `(nextIndex: number) =\u003e void`\n\n## Pager\n\nTODO\n\n## Transformer\n\nTODO\n\n## Scalable Image\n\nTODO\n\n## Examples\n\nThe source code for the example (showcase) app is under the [`Example/`](https://github.com/terrysahaidak/react-native-gallery-toolkit/blob/master/Example/) directory.\nClone the repo, go to the Example/ folder and run:\n\n```bash\nnpm install\n```\n\n### Running on iOS\n\nBefore running the app, install the cocoapods dependencies:\n\n```bash\nnpx pod-install\n```\n\nNow, you can start the app:\n\n```bash\nnpm run ios\n```\n\n### Running on Android\n\n```bash\nnpm run android\n```\n\n## TODOs\n\n- [ ] Add invariants to all the required props\n- [ ] Finish documentation\n- [ ] Lightbox with examples\n- [ ] Lightbox Gallery with examples\n- [ ] Try to use react-native-shared-element\n\n## LICENSE\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fterrysahaidak%2Freact-native-gallery-toolkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fterrysahaidak%2Freact-native-gallery-toolkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fterrysahaidak%2Freact-native-gallery-toolkit/lists"}