UNPKG

@kirz/react-native-toolkit

Version:

Toolkit to speed up React Native development

289 lines (287 loc) 8.93 kB
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } import React, { memo, useCallback, useMemo } from 'react'; import { FlatList, View } from 'react-native'; import { ListViewItem as ListItem } from './ListViewItem'; function groupItems(_ref) { let { sections, numColumns = 1, sectionHeader, sectionFooter, itemSize, spacing = 0 } = _ref; let currentOffset = 0; const flattenSection = (_ref2, sectionIdx) => { let { items: sectionItems, ...section } = _ref2; return [...(sectionHeader ? [{ type: 'header', id: `${section.id ?? sectionIdx}_header` }] : []), ...sectionItems.map((item, itemIndex) => ({ type: 'item', item, itemIndex, id: item.id ?? itemIndex })), ...[...new Array(sectionItems.length % numColumns === 0 ? 0 : numColumns - sectionItems.length % numColumns).keys()].map(idx => ({ type: 'empty', id: `${section.id ?? sectionIdx}_empty_${idx}` })), ...(sectionFooter ? [{ type: 'footer', id: `${section.id ?? sectionIdx}_footer` }] : [])]; }; const groupItems = (flatItems, section, sectionIndex) => { const groupedItems = []; let currentGroup = []; let groupIndex = 0; const wrapGroup = () => { const size = (() => { if (typeof itemSize === 'function') { return Math.max(...currentGroup.filter(x => x.type === 'item').map(x => { const { item, itemIndex } = x; return itemSize({ sectionIndex, section, itemIndex, item: item }); })); } else { return itemSize; } })(); groupedItems.push({ id: `${section.id ?? sectionIndex}_group_${groupIndex}`, type: 'group', section, sectionIndex, items: currentGroup, layout: { length: size, offset: currentOffset } }); currentGroup = []; currentOffset += size; currentOffset += spacing; groupIndex += 1; }; for (let i = 0; i < flatItems.length; i++) { const item = flatItems[i]; if (item.type === 'header') { const size = typeof sectionHeader.size === 'number' ? sectionHeader.size : sectionHeader.size({ sectionIndex, section }); groupedItems.push({ ...item, section, sectionIndex, layout: { length: size, offset: currentOffset } }); currentGroup = []; currentOffset += size; currentOffset += spacing; continue; } if (item.type === 'footer') { const size = typeof sectionFooter.size === 'number' ? sectionFooter.size : sectionFooter.size({ sectionIndex, section }); groupedItems.push({ ...item, section, sectionIndex, layout: { length: size, offset: currentOffset } }); currentGroup = []; currentOffset += size; currentOffset += spacing; continue; } if (currentGroup.length === numColumns - 1) { currentGroup.push(item); wrapGroup(); // eslint-disable-next-line no-continue continue; } currentGroup.push(item); } if (currentGroup.length) { wrapGroup(); } return groupedItems; }; const allGroups = []; sections.forEach((section, sectionIdx) => { const flatSections = flattenSection(section, sectionIdx); const groups = groupItems(flatSections, section, sectionIdx); allGroups.push(...groups); }); return allGroups; } function ListViewInner(_ref3) { let { sections: passedSections, items: passedItems, itemSize, spacing = 0, numColumns = 1, sectionHeader, sectionFooter, flatListProps, style, renderItem: renderContent } = _ref3; const sections = useMemo(() => { if (passedSections) { return passedSections; } return [{ id: '0', items: passedItems }]; }, [passedItems, passedSections]); const items = useMemo(() => { return groupItems({ sections, numColumns, spacing, sectionFooter, sectionHeader, itemSize }); }, [sections, numColumns, spacing]); const getItemLayout = useCallback((data, index) => { if (!data) { return { index: 0, length: 0, offset: 0 }; } const item = data[index]; return { length: item.layout.length + (index < data.length - 1 ? spacing : 0), offset: item.layout.offset, index }; }, [spacing]); const keyExtractor = useCallback(x => x.id, []); const renderItem = useCallback(_ref4 => { let { item } = _ref4; if (item.type === 'header' || item.type === 'footer') { return /*#__PURE__*/React.createElement(ListItem, { section: item.section, sectionIndex: item.sectionIndex, numColumns: 1, itemSize: item.layout.length, spacing: spacing, renderContent: item.type === 'header' ? sectionHeader === null || sectionHeader === void 0 ? void 0 : sectionHeader.renderHeader : sectionFooter === null || sectionFooter === void 0 ? void 0 : sectionFooter.renderFooter }); } if (item.type === 'group') { return /*#__PURE__*/React.createElement(View, { style: { flexDirection: 'row' } }, item.items.filter(x => x.type === 'item').map(x => { const nestedItem = x; return /*#__PURE__*/React.createElement(ListItem, { key: nestedItem.id ?? nestedItem.itemIndex, item: nestedItem.item, itemIndex: nestedItem.itemIndex, section: item.section, sectionIndex: item.sectionIndex, numColumns: numColumns, itemSize: item.layout.length, spacing: spacing, renderContent: renderContent }); })); } return null; }, [numColumns, spacing, renderContent]); const Separator = useMemo(() => () => { return /*#__PURE__*/React.createElement(View, { style: { height: spacing } }); }, [spacing]); return /*#__PURE__*/React.createElement(FlatList, _extends({}, flatListProps, { data: items, numColumns: 1, renderItem: renderItem, style: [{ marginLeft: -spacing }, style], windowSize: (flatListProps === null || flatListProps === void 0 ? void 0 : flatListProps.windowSize) ?? 10, contentInsetAdjustmentBehavior: "never", showsVerticalScrollIndicator: (flatListProps === null || flatListProps === void 0 ? void 0 : flatListProps.showsVerticalScrollIndicator) ?? false, showsHorizontalScrollIndicator: (flatListProps === null || flatListProps === void 0 ? void 0 : flatListProps.showsHorizontalScrollIndicator) ?? false, ItemSeparatorComponent: Separator, getItemLayout: getItemLayout, keyExtractor: (flatListProps === null || flatListProps === void 0 ? void 0 : flatListProps.keyExtractor) ?? keyExtractor // @ts-ignore , listKey: (flatListProps === null || flatListProps === void 0 ? void 0 : flatListProps.keyExtractor) ?? keyExtractor })); } const Memoized = /*#__PURE__*/memo(ListViewInner); function computeSize(_ref5) { let { sections: passedSections, items: passedItems, ...props } = _ref5; const sections = passedSections ? passedSections : [{ id: '0', items: passedItems }]; const groups = groupItems({ ...props, sections, ...(props.sectionHeaderSize && { sectionHeader: { size: props.sectionHeaderSize, renderHeader: () => null } }), ...(props.sectionFooterSize && { renderFooter: { size: props.sectionFooterSize, renderFooter: () => null } }) }); const contentSize = groups.length ? groups[groups.length - 1].layout.length + groups[groups.length - 1].layout.offset : 0; return contentSize + (typeof props.wrapperTotalPaddingSize === 'function' ? props.wrapperTotalPaddingSize({ sections: passedSections, items: passedItems, ...props }) : props.wrapperTotalPaddingSize ?? 0) + (typeof props.wrapperTotalBorderSize === 'function' ? props.wrapperTotalBorderSize({ sections: passedSections, items: passedItems, ...props }) : props.wrapperTotalBorderSize ?? 0); } // @ts-ignore Memoized.computeSize = computeSize; export const ListView = Memoized; //# sourceMappingURL=ListView.js.map