UNPKG

@mpxjs/webpack-plugin

Version:

mpx compile core

200 lines (199 loc) 6.82 kB
import React, { forwardRef, useCallback, useImperativeHandle, useMemo, useRef, useState } from 'react'; import { StyleSheet, Text } from 'react-native'; import MpxPickerView from '../mpx-picker-view'; import MpxPickerViewColumn from '../mpx-picker-view-column'; import { regionData } from './regionData'; import { extendObject, useUpdateEffect } from '../utils'; const styles = StyleSheet.create({ pickerContainer: { height: 240, paddingHorizontal: 10, borderTopLeftRadius: 10, borderTopRightRadius: 10 }, pickerIndicator: { height: 45 }, pickerItem: { fontSize: 16, lineHeight: 45, textAlign: 'center' } }); const rangeProvince = regionData.map(item => item.value); const findIndex = (arr, val) => { const res = arr.findIndex(item => item === val); return res === -1 ? 0 : res; }; const getColumnLength = (level) => { if (level === 'province') { return 1; } else if (level === 'city') { return 2; } else { return 3; } }; const valueStr2Obj = (value = [], limit, customItem = '') => { const offsetIndex = customItem ? 1 : 0; let indexProvince = 0; if (customItem && value[0] === customItem) { indexProvince = 0; } else { indexProvince = findIndex(rangeProvince, value[0]) + offsetIndex; } const ans = { indexArr: [indexProvince], rangeArr: [customItem ? [customItem, ...rangeProvince] : rangeProvince] }; for (let i = 1, lastIndex = indexProvince, lastData = regionData, lastRange = rangeProvince; i < limit; i++) { if (customItem) { if (lastIndex === 0) { if (i === 1) { ans.indexArr.push(0, 0); ans.rangeArr.push([customItem], [customItem]); } else { ans.indexArr.push(0); ans.rangeArr.push([customItem]); } return ans; } } lastData = lastData[lastIndex - offsetIndex].children; lastRange = lastData.map((item) => item.value); lastIndex = findIndex(lastRange, value[i]) + offsetIndex; if (customItem && customItem === value[i]) { lastIndex = 0; } ans.indexArr.push(Math.max(0, lastIndex)); ans.rangeArr.push(customItem ? [customItem, ...lastRange] : lastRange); } return ans; }; const valueChanged2Obj = (currentObj, value, limit = 3, customItem = '') => { const offsetIndex = customItem ? 1 : 0; const newValue = new Array(limit).fill(0); const currentValue = currentObj.indexArr; for (let i = 0; i < limit; i++) { if (i === limit - 1) { return { indexArr: value, rangeArr: currentObj.rangeArr }; } newValue[i] = value[i]; if (currentValue[i] !== value[i]) { break; } } const ans = { indexArr: [newValue[0]], rangeArr: [currentObj.rangeArr[0]] }; let data = regionData; for (let i = 1; i < limit; i++) { if (customItem) { if (newValue[i - 1] === 0) { if (i === 1) { ans.indexArr.push(0, 0); ans.rangeArr.push([customItem], [customItem]); } else { ans.indexArr.push(0); ans.rangeArr.push([customItem]); } return ans; } } data = data[newValue[i - 1] - offsetIndex].children; const range = data.map(item => item.value); ans.indexArr.push(newValue[i]); ans.rangeArr.push(customItem ? [customItem, ...range] : range); } return ans; }; const valueNum2String = (value, customItem = '') => { let data = regionData; return value.map(index => { if (customItem) { if (index === 0) { return customItem; } else { index -= 1; } } const item = data[index]; data = item.children; return item.value; }); }; const hasDiff = (currentValue, value, limit = 3) => { for (let i = 0; i < limit; i++) { if (currentValue[i] !== value[i]) { return true; } } return false; }; const PickerRegion = forwardRef((props, ref) => { const { value = [], level = 'region', 'custom-item': customItem = '', bindchange } = props; const nodeRef = useRef(null); const columnLength = useMemo(() => getColumnLength(level), [level]); const [formatObj, setFormatObj] = useState(valueStr2Obj(value, columnLength, customItem)); const updateValue = useCallback((value = []) => { const calibratedValue = valueStr2Obj(value, columnLength, customItem); setFormatObj(calibratedValue); }, [columnLength, customItem]); const _props = useRef(props); _props.current = props; useImperativeHandle(ref, () => ({ updateValue, getNodeInstance: () => ({ props: _props, nodeRef, instance: { style: {} } }) })); useUpdateEffect(() => { const calibratedValue = valueStr2Obj(value, columnLength, customItem); if (hasDiff(formatObj.indexArr, calibratedValue.indexArr, columnLength)) { setFormatObj(calibratedValue); } }, [value, columnLength, customItem]); const onChange = useCallback((e) => { const { value } = e.detail; const currentValue = formatObj.indexArr; const newObj = valueChanged2Obj(formatObj, value, columnLength, customItem); if (hasDiff(currentValue, value, columnLength)) { setFormatObj(newObj); } bindchange?.({ detail: { value: valueNum2String(newObj.indexArr, customItem) } }); }, [formatObj, columnLength, customItem, bindchange]); const renderColumn = () => { return formatObj.rangeArr?.map((item, index) => ( // @ts-expect-error ignore <MpxPickerViewColumn key={index}> {item.map((item, index) => { const len = item.length; const style = extendObject({}, styles.pickerItem, { fontSize: len > 5 ? 21 - len : 16 }); return <Text key={index} style={style}> {item} </Text>; })} </MpxPickerViewColumn>)); }; return (<MpxPickerView style={styles.pickerContainer} indicator-style={styles.pickerIndicator} value={formatObj.indexArr} bindchange={onChange}> {renderColumn()} </MpxPickerView>); }); PickerRegion.displayName = 'MpxPickerRegion'; export default PickerRegion;