UNPKG

weike-multi-cascader

Version:
165 lines (164 loc) 6.24 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const react_1 = require("react"); const unstated_next_1 = require("unstated-next"); const utils_1 = require("./libs/utils"); const constants_1 = require("./constants"); const useCascade = (params) => { const { data, value: valueProp, selectAll, onChange, onCascaderChange, selectLeafOnly, fristColumMulti, isToolTip } = params || {}; const [popupVisible, setPopupVisible] = react_1.useState(false); const dataRef = react_1.useRef(data); react_1.useEffect(() => { dataRef.current = data; }, [data]); const [flattenData, setFlattenData] = react_1.useState(() => { if (selectAll) { return utils_1.flattenTree([ { title: 'All', value: constants_1.All, parent: null, children: data, }, ]); } return utils_1.flattenTree(data || []); }); react_1.useEffect(() => { setFlattenData(() => { if (selectAll) { return utils_1.flattenTree([ { title: 'All', value: constants_1.All, parent: null, children: data, }, ]); } return utils_1.flattenTree(data || []); }); }, [data, selectAll]); const transformValue = react_1.useCallback((value) => { const nextValue = utils_1.transformValue(value, flattenData); if (onChange && !utils_1.shallowEqualArray(nextValue, value)) { requestAnimationFrame(() => triggerChange(nextValue)); } return nextValue; }, [flattenData]); const [menuData, setMenuData] = react_1.useState(() => { if (selectAll && flattenData.length === 1) { return []; } return [ selectAll ? flattenData[0].children : flattenData.filter((item) => !item.parent), ]; }); const [menuPath, setMenuPath] = react_1.useState([]); const [value, setValue] = react_1.useState(transformValue(valueProp || [])); const hackValue = react_1.useRef(value); const selectedItems = react_1.useMemo(() => { return flattenData.filter((node) => { return (valueProp || hackValue.current).includes(node.value); }); }, [flattenData, valueProp, popupVisible, hackValue.current]); const triggerChange = react_1.useCallback((nextValue) => { // 根据最新的value 返回实际内容 const returnItem = (value) => { return flattenData.filter((node) => { return value.includes(node.value); }); }; if (onChange) { onChange(nextValue, returnItem(nextValue)); } hackValue.current = nextValue; setValue(nextValue); // setPopupVisible(false) }, [selectedItems]); const addMenu = react_1.useCallback((menu, index) => { if (menu && menu.length) { setMenuData((prevMenuData) => [...prevMenuData.slice(0, index), menu]); } else { setMenuData((prevMenuData) => [...prevMenuData.slice(0, index)]); } }, []); const addChildrenToNode = react_1.useCallback((target, children) => { const found = utils_1.findNodeByValue(target.value, dataRef.current); if (found) { found.children = children; } return [...dataRef.current]; }, []); const lastItemRef = react_1.useRef(null); const handleCascaderChange = react_1.useCallback((item, depth) => { const { children } = item; lastItemRef.current = item; onCascaderChange === null || onCascaderChange === void 0 ? void 0 : onCascaderChange(item, { add: (newChildren) => { const newData = addChildrenToNode(item, newChildren); if (lastItemRef.current === item) { item.children = newChildren; newChildren.forEach((child) => { child.parent = item; }); setFlattenData((prev) => [...prev, ...newChildren]); handleCascaderChange(item, depth); } return newData; }, }); addMenu(children, depth + 1); setMenuPath((prevMenuPath) => prevMenuPath.slice(0, depth).concat(item)); }, [menuPath, onCascaderChange]); const handleSelectChange = react_1.useCallback((item, checked) => { setValue((prevValue) => { triggerChange(utils_1.sortByTree(utils_1.reconcile(item, checked, prevValue), flattenData)); return utils_1.sortByTree(utils_1.reconcile(item, checked, prevValue), flattenData); }); }, [flattenData]); const resetMenuState = react_1.useCallback(() => { if (selectAll && flattenData.length === 1) { return setMenuData([]); } else { setMenuData([ selectAll ? flattenData[0].children : flattenData.filter((item) => !item.parent), ]); } setMenuPath([]); }, [flattenData, selectAll]); // 传入的 value 有变更时重新计算 react_1.useEffect(() => { if (popupVisible) { setValue(transformValue(valueProp || hackValue.current)); resetMenuState(); } }, [popupVisible]); return { menuPath, popupVisible, setPopupVisible, menuData, addMenu, setMenuData, value, setValue, handleCascaderChange, handleSelectChange, flattenData, resetMenuState, selectedItems, triggerChange, selectLeafOnly, hackValue, fristColumMulti, isToolTip }; }; exports.default = unstated_next_1.createContainer(useCascade);