react-native-flash-section-list
Version:
SectionList for React Native using FlashList
139 lines • 5.78 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = SectionIndex;
const react_1 = __importStar(require("react"));
const react_native_1 = require("react-native");
function SectionIndex({ dark = false, barContainerStyle = {}, barStyle = {}, textStyle = {}, data, fontSize: propFontSize = 10, getLabel = (data) => { var _a; return (_a = data.char) === null || _a === void 0 ? void 0 : _a.substring(0, 1); }, onPressIndex = (_d, _i) => { }, }) {
const { fontScale } = (0, react_native_1.useWindowDimensions)();
const fontSize = Math.ceil(propFontSize * fontScale);
const styles = makeStyles(dark, fontSize);
const indexRef = (0, react_1.useRef)(0);
const [barYPos, setBarYPos] = (0, react_1.useState)(0);
const [barHeight, setBarHeight] = (0, react_1.useState)(0);
const [indexData, setIndexData] = (0, react_1.useState)([]);
const [visibleCharCount, setVisibleCharCount] = (0, react_1.useState)(0);
(0, react_1.useEffect)(() => {
if (visibleCharCount === 0) {
return;
}
if (data.length <= visibleCharCount) {
setIndexData(data);
return;
}
const ellipsisVisibleCharCount = Math.round(visibleCharCount / 2);
let ellipsisCount = 2;
let ellipsisList = data.filter((_, i) => i % ellipsisCount === 0);
while (ellipsisList.length != 0 &&
ellipsisList.length > ellipsisVisibleCharCount) {
ellipsisCount++;
ellipsisList = data.filter((_, i) => i % ellipsisCount === 0);
}
ellipsisList[ellipsisList.length - 1] = data[data.length - 1];
setIndexData(ellipsisList
.map((d) => [d, { char: "・", actualIndex: -1 }])
.flat()
.slice(0, -1));
}, [data, visibleCharCount]);
const onBarVisibleAreaLayout = (0, react_1.useCallback)((e) => {
const { height } = e.nativeEvent.layout;
const visibleCharCount = Math.floor(height / fontSize);
setVisibleCharCount(visibleCharCount);
}, [propFontSize, fontScale]);
const onLayout = (0, react_1.useCallback)((e) => {
e.target.measure((_x, _y, _width, height, _pageX, pageY) => {
setBarYPos(pageY + 8);
const visibleHeight = height - 16;
setBarHeight(visibleHeight);
});
}, [setBarYPos, setBarHeight]);
const onPress = (0, react_1.useCallback)((data, pageY) => {
const y = pageY - barYPos;
if (y < 0 || barHeight < y) {
return;
}
let index = Math.round((y / barHeight) * (data.length - 1));
index = index < 0 ? 0 : data.length <= index ? data.length - 1 : index;
if (indexRef.current === index) {
return;
}
indexRef.current = index;
onPressIndex(data[index], index);
}, [onPressIndex, barYPos, barHeight]);
// タップイベント
const panResponder = react_native_1.PanResponder.create({
onStartShouldSetPanResponder: () => true,
onMoveShouldSetPanResponder: () => true,
onPanResponderGrant: (e) => {
onPress(data, e.nativeEvent.pageY);
},
onPanResponderMove: (e) => {
onPress(data, e.nativeEvent.pageY);
},
});
return (<react_native_1.View style={styles.sectionIndexContainer}>
<react_native_1.View style={[styles.barVisibleArea, barContainerStyle]} onLayout={onBarVisibleAreaLayout}>
<react_native_1.View style={[{ opacity: 1 }, styles.bar, barStyle]} onLayout={onLayout}>
<react_native_1.View style={styles.touchArea} {...panResponder.panHandlers}>
{indexData.map((v, i) => (<react_native_1.Text key={i} style={[styles.text, textStyle]}>
{getLabel(v)}
</react_native_1.Text>))}
</react_native_1.View>
</react_native_1.View>
</react_native_1.View>
</react_native_1.View>);
}
const makeStyles = (dark, fontSize) => react_native_1.StyleSheet.create({
sectionIndexContainer: {
right: 0,
width: fontSize + 10,
marginLeft: -(fontSize + 10),
height: "100%",
justifyContent: "center",
},
barVisibleArea: {
height: "95%",
justifyContent: "center",
},
bar: {
maxHeight: "100%",
overflow: "hidden",
paddingVertical: 8,
},
touchArea: {
justifyContent: "space-between",
paddingHorizontal: 4,
width: "100%",
},
text: {
color: dark ? "#ffffffee" : "#111",
fontSize,
height: fontSize,
lineHeight: fontSize,
textAlign: "center",
overflow: "visible",
},
});
//# sourceMappingURL=SectionIndex.js.map