@kirz/react-native-toolkit
Version:
Toolkit to speed up React Native development
289 lines (287 loc) • 8.93 kB
JavaScript
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