{"_id":"@dianshu/react-native-collapsible-tab-view","name":"@dianshu/react-native-collapsible-tab-view","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@dianshu/react-native-collapsible-tab-view","version":"1.0.0","description":"Collapsible tab view component for React Native","main":"lib/commonjs/index.js","react-native":"src/index.tsx","module":"lib/module/index.js","types":"lib/typescript/src/index.d.ts","scripts":{"test":"jest","typescript":"tsc --noEmit","lint":"eslint --ext .js,.ts,.tsx .","release":"release-it","example":"yarn --cwd example","bootstrap":"yarn example && yarn","prepack":"bob build","docs":"ts-node ./documentation/buildDocs.ts","prepare":"bob build && husky install"},"publishConfig":{"registry":"https://registry.npmjs.org/"},"keywords":["react-native-component","react-component","react-native","ios","android","tab","swipe","scrollable","coverflow"],"repository":{"type":"git","url":"git+https://github.com/PedroBern/react-native-collapsible-tab-view.git"},"author":{"name":"Pedro Bern","email":"pedrobermoreira@gmail.com","url":"https://github.com/pedrobern/"},"license":"MIT","bugs":{"url":"https://github.com/pedrobern/react-native-collapsible-tab-view/issues"},"homepage":"https://github.com/PedroBern/react-native-collapsible-tab-view#readme","devDependencies":{"@commitlint/config-conventional":"^19.1.0","@microsoft/tsdoc":"^0.14.2","@release-it/conventional-changelog":"^8.0.1","@shopify/flash-list":"^1.6.4","@types/react":"~18.2.74","@types/react-native":"0.73.0","babel-jest":"^29.7.0","babel-preset-react-native":"^4.0.1","commitlint":"^19.2.1","eslint":"^8.57.0","eslint-config-universe":"^12.0.0","eslint-plugin-react":"^7.34.0","eslint-plugin-react-native":"^4.1.0","eslint-plugin-react-native-globals":"^0.1.2","husky":"^9.0.11","jest":"^29.7.0","prettier":"^3.2.5","react":"~18.2.0","react-docgen-typescript":"^1.20.5","react-native":"~0.73.6","react-native-builder-bob":"^0.18.2","react-native-gesture-handler":"~2.16.0","react-native-pager-view":"^6.3.0","react-native-reanimated":"3.8.1","release-it":"^17.1.1","ts-node":"^10.9.2","typescript":"^5.4.3"},"peerDependencies":{"@shopify/flash-list":">=1.0.0","react":"*","react-native":"*","react-native-pager-view":"*","react-native-reanimated":">=3.8.1"},"peerDependenciesMeta":{"@shopify/flash-list":{"optional":true}},"jest":{"preset":"react-native","modulePathIgnorePatterns":["<rootDir>/example/node_modules","<rootDir>/lib/"]},"@react-native-community/bob":{"source":"src","output":"lib","targets":["commonjs","module",["typescript",{"project":"tsconfig.build.json"}]]},"dependencies":{"use-deep-compare":"^1.1.0"},"packageManager":"yarn@1.22.11","react-native-builder-bob":{"source":"src","output":"lib","targets":["commonjs","module","typescript"]},"eslintIgnore":["node_modules/","lib/"],"_id":"@dianshu/react-native-collapsible-tab-view@1.0.0","gitHead":"88000ccc38884c1c60cc06af0d149dd208bafbf1","_nodeVersion":"20.18.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-ZXfMKRTyWPCeLuQxWZsdnQPLs57+D7C7TpVFENpm8B1qIWNtya3DGN6joKonvIg5XEIQe/+lLTbqLA9GuIZiyw==","shasum":"8b2e29c581f5bf3a1050d6fea5ebbeff29120a4e","tarball":"https://registry.npmjs.org/@dianshu/react-native-collapsible-tab-view/-/react-native-collapsible-tab-view-1.0.0.tgz","fileCount":114,"unpackedSize":548983,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC/YJn/Re/fkZR+DiMhwx1/ZWL2BSHlcWizys9agH8uJAiBN48ez3KTzY1le6y51V7M2ge14urPFQSfWnvnM/1dXOA=="}]},"_npmUser":{"name":"dianshu","email":"loadingsong@qq.com"},"directories":{},"maintainers":[{"name":"dianshu","email":"loadingsong@qq.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/react-native-collapsible-tab-view_1.0.0_1732399649838_0.03420745220948995"},"_hasShrinkwrap":false}},"time":{"created":"2024-11-23T22:07:29.738Z","1.0.0":"2024-11-23T22:07:30.031Z","modified":"2024-11-23T22:07:30.312Z"},"maintainers":[{"name":"dianshu","email":"loadingsong@qq.com"}],"description":"Collapsible tab view component for React Native","homepage":"https://github.com/PedroBern/react-native-collapsible-tab-view#readme","keywords":["react-native-component","react-component","react-native","ios","android","tab","swipe","scrollable","coverflow"],"repository":{"type":"git","url":"git+https://github.com/PedroBern/react-native-collapsible-tab-view.git"},"author":{"name":"Pedro Bern","email":"pedrobermoreira@gmail.com","url":"https://github.com/pedrobern/"},"bugs":{"url":"https://github.com/pedrobern/react-native-collapsible-tab-view/issues"},"license":"MIT","readme":"# React Native Collapsible Tab View\n\n[![Build Status][build-badge]][build]\n[![Version][version-badge]][package]\n[![MIT License][license-badge]][license]\n[![Runs with Expo][expo-badge]][expo]\n\n- [Expo App](#expo-app)\n- [Demo](#demo)\n- [Features](#features)\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [Guides](#guides)\n  - [Scroll on Header](#scroll-on-header)\n- [API Reference](#api-reference)\n  - [Core](#core)\n    - [Tabs.Container](#tabscontainer)\n    - [Tabs.Lazy](#tabslazy)\n    - [Tabs.FlatList](#tabsflatlist)\n    - [Tabs.FlashList](#tabsflatlist)\n    - [Tabs.MasonryFlashList](#tabsmasonryflatlist)\n    - [Tabs.SectionList](#tabssectionlist)\n    - [Tabs.ScrollView](#tabsscrollview)\n    - [Ref](#ref)\n  - [Hooks](#hooks)\n    - [useCollapsibleStyle](#usecollapsiblestyle)\n    - [useAnimatedTabIndex](#useanimatedtabindex)\n    - [useFocusedTab](#usefocusedtab)\n    - [useHeaderMeasurements](#useheadermeasurements)\n  - [Default Tab Bar](#default-tab-bar)\n    - [MaterialTabBar](#materialtabbar)\n    - [MaterialTabItem](#materialtabitem)\n- [Known Issues](#known-issues)\n  - [Android FlatList Pull to Refresh](#android-flatlist-pull-to-refresh)\n  - [iOS FlatList StickyHeaderIndices](#ios-flatlist-stickyheaderindices)\n  - [ref.setIndex](#refsetindex)\n- [Alternative Libraries](#alternative-libraries)\n- [Contributing](#contributing)\n  - [Documentation Changes](#documentation-changes)\n\n## 🚀 Version 6 released with Reanimated v3 support\n\nReact Native Collapsible Tab View is a versatile library for creating collapsible tab views using [Reanimated](https://github.com/software-mansion/react-native-reanimated).\n\n- Explore the [examples](https://github.com/PedroBern/react-native-collapsible-tab-view/tree/main/example) for the source code of the Expo app.\n\n**Credits**\n\nThe [react-native-tab-view](https://github.com/satya164/react-native-tab-view) example app was used as a template for the demos.\n\n# Demo\n\n|                                                     Default                                                      |                                                     Snap                                                      |                                                revealHeaderOnScroll                                                |                                               revealHeaderOnScroll + Snap                                               |\n| :--------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------: |\n| <img src=\"https://github.com/PedroBern/react-native-collapsible-tab-view/raw/main/demo/default.gif\" width=\"360\"> | <img src=\"https://github.com/PedroBern/react-native-collapsible-tab-view/raw/main/demo/snap.gif\" width=\"360\"> | <img src=\"https://github.com/PedroBern/react-native-collapsible-tab-view/raw/main/demo/diffClamp.gif\" width=\"360\"> | <img src=\"https://github.com/PedroBern/react-native-collapsible-tab-view/raw/main/demo/diffClamp_snap.gif\" width=\"360\"> |\n\n# Features\n\n- UI thread animations and interactions\n- High customizability\n- Full [TypeScript](https://typescriptlang.org) support\n- Lazy loading with fade-in animation\n- DiffClamp header\n- Interpolated header\n- Scroll snap (with interpolated header)\n- Animated snap (with diffClamp header)\n- Scrollable tabs, inspired by the [react-native-tab-view](https://github.com/satya164/react-native-tab-view) tab bar\n\n# Installation\n\nTo install the library, open a terminal in your project's root directory and run:\n\n```sh\nyarn add react-native-collapsible-tab-view react-native-pager-view\n```\n\nThen, add [Reanimated](https://docs.swmansion.com/react-native-reanimated), [follow the official installation guide](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/installation).\n\n# Quick Start\n\n```tsx\nimport React from 'react'\nimport { View, StyleSheet, ListRenderItem } from 'react-native'\nimport { Tabs } from 'react-native-collapsible-tab-view'\n\nconst HEADER_HEIGHT = 250\n\nconst DATA = [0, 1, 2, 3, 4]\nconst identity = (v: unknown): string => v + ''\n\nconst Header = () => {\n  return <View style={styles.header} />\n}\n\nconst Example: React.FC = () => {\n  const renderItem: ListRenderItem<number> = React.useCallback(({ index }) => {\n    return (\n      <View style={[styles.box, index % 2 === 0 ? styles.boxB : styles.boxA]} />\n    )\n  }, [])\n\n  return (\n    <Tabs.Container\n      renderHeader={Header}\n      headerHeight={HEADER_HEIGHT} // optional\n    >\n      <Tabs.Tab name=\"A\">\n        <Tabs.FlatList\n          data={DATA}\n          renderItem={renderItem}\n          keyExtractor={identity}\n        />\n      </Tabs.Tab>\n      <Tabs.Tab name=\"B\">\n        <Tabs.ScrollView>\n          <View style={[styles.box, styles.boxA]} />\n          <View style={[styles.box, styles.boxB]} />\n        </Tabs.ScrollView>\n      </Tabs.Tab>\n    </Tabs.Container>\n  )\n}\n\nconst styles = StyleSheet.create({\n  box: {\n    height: 250,\n    width: '100%',\n  },\n  boxA: {\n    backgroundColor: 'white',\n  },\n  boxB: {\n    backgroundColor: '#D8D8D8',\n  },\n  header: {\n    height: HEADER_HEIGHT,\n    width: '100%',\n    backgroundColor: '#2196f3',\n  },\n})\n\nexport default Example\n\n```\n\n# Guides\n\n## Scrolling on the Header\n\nTo enable scrolling from the header, follow these steps:\n\n- If the `HeaderComponent` **does not** contain touchable components, set the `pointerEvents` prop to `'none'`.\n- If the `HeaderComponent` **does** contain touchable components, set the `pointerEvents` prop to `'box-none'` to ensure they function properly.\n\nNote: If any child component within the `HeaderComponent` should **not** respond to touches, such as an `<Image />` element, set its `pointerEvents` prop to `'none'`. Otherwise, it may unintentionally become the target of a touch gesture on iOS devices and prevent scrolling.\n\n# API Reference\n\n## Core\n\n### Tabs.Container\n\nBasic usage looks like this:\n\n```tsx\nimport { Tabs } from 'react-native-collapsible-tab-view'\n\nconst Example = () => {\n   return (\n     <Tabs.Container renderHeader={MyHeader}>\n       <Tabs.Tab name=\"A\">\n         <ScreenA />\n       </Tabs.Tab>\n       <Tabs.Tab name=\"B\">\n         <ScreenB />\n       </Tabs.Tab>\n     </Tabs.Container>\n   )\n}\n```\n\n#### Props\n\n|name|type|default|description|\n|:----:|:----:|:----:|:----:|\n|`allowHeaderOverscroll`|`boolean \\| undefined`|`false`|Whether the header moves down during overscrolling (for example on pull-to-refresh on iOS) or sticks to the top|\n|`cancelLazyFadeIn`|`boolean \\| undefined`|||\n|`cancelTranslation`|`boolean \\| undefined`|||\n|`containerStyle`|`StyleProp<ViewStyle>`|||\n|`headerContainerStyle`|`StyleProp<AnimateStyle<ViewStyle>>`|||\n|`headerHeight`|`number \\| undefined`||Is optional, but will optimize the first render.|\n|`initialTabName`|`string \\| undefined`|||\n|`lazy`|`boolean \\| undefined`||If lazy, will mount the screens only when the tab is visited. There is a default fade in transition.|\n|`minHeaderHeight`|`number \\| undefined`||Header minimum height when collapsed|\n|`onIndexChange`|`((index: number) => void) \\| undefined`||Callback fired when the index changes. It receives the current index.|\n|`onTabChange`|`(data: { prevIndex: number index: number prevTabName: T tabName: T }) => void`||Callback fired when the tab changes. It receives the previous and current index and tabnames.|\n|`pagerProps`|`Omit<FlatListProps<number>, 'data' \\| 'keyExtractor' \\| 'renderItem' \\| 'horizontal' \\| 'pagingEnabled' \\| 'onScroll' \\| 'showsHorizontalScrollIndicator' \\| 'getItemLayout'>`||Props passed to the pager. If you want for example to disable swiping, you can pass `{ scrollEnabled: false }`|\n|`renderHeader`|`(props: TabBarProps<TabName>) => React.ReactElement \\| null`|||\n|`renderTabBar`|`(props: TabBarProps<TabName>) => React.ReactElement \\| null`|`(props: TabBarProps<TabName>) => MaterialTabBar`||\n|`revealHeaderOnScroll`|`boolean \\| undefined`||Reveal header when scrolling down. Implements diffClamp.|\n|`snapThreshold`|`number \\| null \\| undefined`|`null`|Percentage of header height to define as the snap point. A number between 0 and 1, or `null` to disable snapping.|\n|`tabBarHeight`|`number \\| undefined`||Is optional, but will optimize the first render.|\n|`width`|`number \\| undefined`||Custom width of the container. Defaults to the window width.|\n\n### Tabs.Tab\n\nWrap your screens with `Tabs.Tab`. Basic usage looks like this:\n\n```tsx\n<Tabs.Container ...>\n  <Tabs.Tab name=\"A\" label=\"First Tab\">\n   <ScreenA />\n  </Tabs.Tab>\n  <Tabs.Tab name=\"B\">\n   <ScreenA />\n  </Tabs.Tab>\n</Tabs.Container>\n```\n\n#### Props\n\n|name|type|\n|:----:|:----:|\n|`label`|`string \\| ((props: TabItemProps<T>) => ReactNode) \\| undefined`|\n|`name`|`T`|\n\n### Tabs.Lazy\n\nTypically used internally, but if you want to mix lazy and regular screens you can wrap the lazy ones with this component.\n\n#### Props\n\n|name|type|\n|:----:|:----:|\n|`cancelLazyFadeIn`|`boolean \\| undefined`|\n|`startMounted`|`boolean \\| undefined`|\n\n### Tabs.FlatList\n\nUse like a regular FlatList.\n\n### Tabs.FlashList\n\nUse like a regular FlashList.\n\n### Tabs.MasonryFlashList\n\nUse like a regular MasonryFlashList.\n\n### Tabs.ScrollView\n\nUse like a regular ScrollView.\n\n### Tabs.SectionList\n\nUse like a regular SectionList.\n\n\n\n### Ref\n\nYou can pass a ref to `Tabs.Container`.\n\n```tsx\nconst ref = React.useRef()\n<Tabs.Container ref={ref}>\n```\n\n|     method      |             type             |\n| :-------------: | :--------------------------: |\n|    jumpToTab    |    `(name: T) => boolean`    |\n|    setIndex     | `(index: number) => boolean` |\n|  getFocusedTab  |          `() => T`           |\n| getCurrentIndex |        `() => number`        |\n\n## Hooks\n\n### `useCollapsibleStyle`\n\nThis hook provides access to key styles for the collapsible tab view. It can be used to obtain the `progressViewOffset` and pass it to the `RefreshControl` of the scroll view.\n\n```tsx\nconst {\n  contentContainerStyle,\n  progressViewOffset,\n  style,\n} = useCollapsibleStyle()\n```\n\n#### Values\n\n|         name          |                     type                     |\n| :-------------------: | :------------------------------------------: |\n| contentContainerStyle | `{ minHeight: number; paddingTop: number; }` |\n|  progressViewOffset   |                   `number`                   |\n|         style         |             `{ width: number; }`             |\n\n### `useAnimatedTabIndex`\n\nThis hook returns an animated value representing the current tab index. As the tab view can be in between panes while swiping, this value is a floating-point number.\n\n```tsx\nconst tabIndex = useAnimatedTabIndex()\n```\n\n### `useFocusedTab`\n\nThis hook returns the name of the currently focused tab.\n\n```tsx\nconst focusedTab = useFocusedTab()\n```\n\n### `useHeaderMeasurements`\n\nThis hook returns the top distance and the header height. For an example of how to use this, check out the animated header example in the example folder.\n\n```tsx\nconst { top, height } = useHeaderMeasurements()\n```\n\n### useCurrentTabScrollY\n\nThis hook returns the vertical scroll position of the current tab as an Animated SharedValue. \n\nSince this library requires handling the `onScroll` event for its functionality, this is the only way to react to changes in the scroll position of the underlying scrollable component.\n\n\n```tsx\nconst scrollY = useCurrentTabScrollY()\n```\n\n\n## Default Tab Bar\n\n### MaterialTabItem\n\nAny additional props are passed to the pressable component.\n\n#### Props\n\n|name|type|description|\n|:----:|:----:|:----:|\n|`activeColor`|`string \\| undefined`|Color applied to the label when active|\n|`inactiveColor`|`string \\| undefined`|Color applied to the label when inactive|\n|`inactiveOpacity`|`number \\| undefined`||\n|`index`|`number`||\n|`indexDecimal`|`SharedValue<number>`||\n|`label`|`string \\| ((props: TabItemProps<T>) => ReactNode)`||\n|`labelStyle`|`StyleProp<AnimateStyle<TextStyle>>`|Style to apply to the tab item label|\n|`name`|`T`||\n|`onLayout`|`(((event: LayoutChangeEvent) => void) & ((event: LayoutChangeEvent) => void)) \\| undefined`|Invoked on mount and layout changes with {nativeEvent: { layout: {x, y, width, height}}}.|\n|`onPress`|`(name: T) => void`||\n|`pressColor`|`string \\| undefined`||\n|`pressOpacity`|`number \\| undefined`||\n|`scrollEnabled`|`boolean \\| undefined`||\n|`style`|`StyleProp<ViewStyle>`|Either view styles or a function that receives a boolean reflecting whether the component is currently pressed and returns view styles.|\n\n\n\n# Known Issues\n\n## Android FlatList Pull to Refresh\n\nRefer to [this open issue](https://github.com/software-mansion/react-native-reanimated/issues/1703). We utilize [scrollTo](https://docs.swmansion.com/react-native-reanimated/docs/next/api/nativeMethods/scrollTo) to synchronize the unfocused tabs. While it is intended for use with `ScrollView`, it works well with `FlatList`, until the `RefreshControl` is added. Note that this issue occurs only on Android.\n\n**Workaround**: Check out the `Android Shared Pull To Refresh` example in the expo app. You can implement a single pull-to-refresh for the `Tabs.Container`.\n\n## iOS FlatList StickyHeaderIndices and iOS SectionList StickySectionHeadersEnabled\n\nWhen using the `stickyHeaderIndices` prop on a FlatList or `stickySectionHeadersEnabled` on a SectionList, the sticky elements do not scroll up as the header collapses. This issue is specific to iOS.\n\nSee [#136](https://github.com/PedroBern/react-native-collapsible-tab-view/issues/136).\n\n## `ref.setIndex`\n\nThis is not an issue per se, but it's essential to be aware of it. When using `containerRef.current.setIndex(i)`, if you set it to the current index, the screen will scroll to the top. You can prevent this behavior as follows:\n\n\n```ts\nconst index = pageRef.current?.getCurrentIndex()\nif (index !== nextIndex) {\n  pageRef.current?.setIndex(nextIndex)\n}\n```\n\n# Alternative Libraries\n\nIf you do not require a full-featured tab view, consider another option: a simple segmented control / material tab bar without swiping or snapping, using only the React Native Animated API.\n\n- [react-native-collapsible-segmented-view](https://github.com/PedroBern/react-native-collapsible-segmented-view)\n\n# Contributing and running the Example\n\nWhile developing, you can run the [example app](/example/README.md) to test your changes.\n\nFirst run `yarn` in root:\n```sh\nyarn\n```\n\nThen prepare the example:\n```sh\ncd example\nyarn\n```\n\nThen run the example:\n```\nyarn ios\n```\n\nPlease follow the [angular commit message format](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-commit-message-format).\n\nMake sure your code passes TypeScript and ESLint. Run the following to verify:\n\n```sh\nyarn typescript\nyarn lint\n```\n\nTo fix formatting errors, run the following:\n\n```sh\nyarn lint -- --fix\n```\n\n## Documentation changes\n\nEdit the [README_TEMPLATE](https://github.com/PedroBern/react-native-collapsible-tab-view/tree/main/documentation/README_TEMPLATE.md), or update the docstrings inside the `src` folder, and run:\n\n```sh\nyarn docs\n```\n\n<!-- badges -->\n\n[build-badge]: https://img.shields.io/circleci/build/github/PedroBern/react-native-collapsible-tab-view/main.svg?style=flat-square\n[build]: https://app.circleci.com/pipelines/github/PedroBern/react-native-collapsible-tab-view\n[version-badge]: https://img.shields.io/npm/v/react-native-collapsible-tab-view.svg?style=flat-square\n[package]: https://www.npmjs.com/package/react-native-collapsible-tab-view\n[license-badge]: https://img.shields.io/npm/l/react-native-collapsible-tab-view.svg?style=flat-square\n[license]: https://opensource.org/licenses/MIT\n[expo-badge]: https://img.shields.io/badge/Runs%20with%20Expo-4630EB.svg?style=flat-square&logo=EXPO&labelColor=f3f3f3&logoColor=000\n[expo]: https://github.com/expo/expo\n","readmeFilename":"README.md"}