Repository: jsoendermann/rn-section-list-get-item-layout Branch: master Commit: 9a84aa32b703 Files: 8 Total size: 7.0 KB Directory structure: gitextract_u9961okd/ ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── index.spec.js ├── index.ts ├── package.json └── tsconfig.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ node_modules yarn-error.log dist coverage .DS_Store ================================================ FILE: .npmignore ================================================ .gitignore tsconfig.json index.ts index.spec.js coverage .DS_Store ================================================ FILE: LICENSE ================================================ Copyright (c) 2017 Jan Soendermann Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ # React Native SectionList getItemLayout This package provides a function that helps you construct the `getItemLayout` function for your `SectionList`s. For an explanation of why this exists, see [this post](https://medium.com/@jsoendermann/sectionlist-and-getitemlayout-2293b0b916fb). It's meant to be used like this: ```javascript import sectionListGetItemLayout from 'react-native-section-list-get-item-layout' class MyComponent extends React.Component { constructor(props) { super(props) this.getItemLayout = sectionListGetItemLayout({ // The height of the row with rowData at the given sectionIndex and rowIndex getItemHeight: (rowData, sectionIndex, rowIndex) => sectionIndex === 0 ? 100 : 50, // These four properties are optional getSeparatorHeight: () => 1 / PixelRatio.get(), // The height of your separators getSectionHeaderHeight: () => 20, // The height of your section headers getSectionFooterHeight: () => 10, // The height of your section footers listHeaderHeight: 40, // The height of your list header }) } render() { return ( ) } } ``` ================================================ FILE: index.spec.js ================================================ const sectionListGetItemLayout = require('./dist').default test('Empty sections', () => { const getItemLayout = sectionListGetItemLayout({ getItemHeight: () => 2, getSeparatorHeight: () => 23, getSectionHeaderHeight: () => 41, getSectionFooterHeight: () => 61, }) const data = [{ data: [] }, { data: [] }, { data: [null] }] expect(getItemLayout(data, 0)).toEqual({ length: 41, offset: 0, index: 0 }) expect(getItemLayout(data, 1)).toEqual({ length: 61, offset: 41, index: 1 }) expect(getItemLayout(data, 5)).toEqual({ length: 2, offset: 41 * 3 + 61 * 2, index: 5, }) expect(getItemLayout(data, 6)).toEqual({ length: 61, offset: 41 * 3 + 61 * 2 + 2, index: 6, }) }) test('Multiple rows in one section', () => { const getItemLayout = sectionListGetItemLayout({ getItemHeight: () => 2, getSeparatorHeight: () => 23, getSectionHeaderHeight: () => 41, getSectionFooterHeight: () => 61, }) const data = [{ data: [null, null, null] }] expect(getItemLayout(data, 2)).toEqual({ length: 2, offset: 41 + 2 + 23, index: 2, }) }) test('Calling sectionListGetItemLayout with only getItemHeight', () => { const getItemLayout = sectionListGetItemLayout({ getItemHeight: () => 1, }) const data = [{ data: [null, null] }] expect(getItemLayout(data, 0)).toEqual({ length: 0, offset: 0, index: 0 }) expect(getItemLayout(data, 1)).toEqual({ length: 1, offset: 0, index: 1 }) expect(getItemLayout(data, 2)).toEqual({ length: 1, offset: 1, index: 2 }) expect(getItemLayout(data, 3)).toEqual({ length: 0, offset: 2, index: 3 }) }) ================================================ FILE: index.ts ================================================ export type SectionListDataProp = Array<{ title: string data: any[] }> interface SectionHeader { type: 'SECTION_HEADER' } interface Row { type: 'ROW' index: number } interface SectionFooter { type: 'SECTION_FOOTER' } type ListElement = SectionHeader | Row | SectionFooter export interface Parameters { getItemHeight: ( rowData: any, sectionIndex: number, rowIndex: number, ) => number getSeparatorHeight?: (sectionIndex: number, rowIndex: number) => number getSectionHeaderHeight?: (sectionIndex: number) => number getSectionFooterHeight?: (sectionIndex: number) => number listHeaderHeight?: number | (() => number) } export default ({ getItemHeight, getSeparatorHeight = () => 0, getSectionHeaderHeight = () => 0, getSectionFooterHeight = () => 0, listHeaderHeight = 0, }: Parameters) => (data: SectionListDataProp, index: number) => { let i = 0 let sectionIndex = 0 let elementPointer: ListElement = { type: 'SECTION_HEADER' } let offset = typeof listHeaderHeight === 'function' ? listHeaderHeight() : listHeaderHeight while (i < index) { switch (elementPointer.type) { case 'SECTION_HEADER': { const sectionData = data[sectionIndex].data offset += getSectionHeaderHeight(sectionIndex) // If this section is empty, we go right to the footer... if (sectionData.length === 0) { elementPointer = { type: 'SECTION_FOOTER' } // ...otherwise we make elementPointer point at the first row in this section } else { elementPointer = { type: 'ROW', index: 0 } } break } case 'ROW': { const sectionData = data[sectionIndex].data const rowIndex = elementPointer.index offset += getItemHeight(sectionData[rowIndex], sectionIndex, rowIndex) elementPointer.index += 1 if (rowIndex === sectionData.length - 1) { elementPointer = { type: 'SECTION_FOOTER' } } else { offset += getSeparatorHeight(sectionIndex, rowIndex) } break } case 'SECTION_FOOTER': { offset += getSectionFooterHeight(sectionIndex) sectionIndex += 1 elementPointer = { type: 'SECTION_HEADER' } break } } i += 1 } let length switch (elementPointer.type) { case 'SECTION_HEADER': length = getSectionHeaderHeight(sectionIndex) break case 'ROW': const rowIndex = elementPointer.index length = getItemHeight( data[sectionIndex].data[rowIndex], sectionIndex, rowIndex, ) break case 'SECTION_FOOTER': length = getSectionFooterHeight(sectionIndex) break default: throw new Error('Unknown elementPointer.type') } return { length, offset, index } } ================================================ FILE: package.json ================================================ { "name": "react-native-section-list-get-item-layout", "version": "2.2.3", "description": "This package simplifies constructing the getItemLayout prop for react native SectionLists.", "main": "./dist/index.js", "typings": "./dist/index.d.ts", "license": "Apache-2.0", "author": { "name": "Jan Soendermann", "email": "jan.soendermann+npm@gmail.com" }, "scripts": { "ts:build": "tsc", "ts:watch": "tsc --watch", "test": "jest", "prepublish": "npm run ts:build" }, "devDependencies": { "jest": "^22.4.4", "typescript": "^2.8.3" } } ================================================ FILE: tsconfig.json ================================================ { "compilerOptions": { "target": "es3", "strict": true, "sourceMap": true, "declaration": true, "outDir": "dist" }, "include": [ "index.ts" ] }