/** * Particial Methods Collection */ import * as React from "react"; import { NodeElement, Key, DataNode, DataEntity, NodeInstance } from "../interface"; import TreeNode, { TreeNodeProps } from "../tree-node"; import { TreeProps } from "../tree"; //Constant about Drag Event const DRAG_SIDE_RANGE = 0.25; const DRAG_MIN_GAP = 2; //To Array const toArray = (children: React.ReactNode): React.ReactElement[] => { const arrg = []; React.Children.forEach(children, c => { arrg.push(c); }); return arrg; }; //Delete Array const arrDel = (list: Key[], value: Key) => { const clone = list.slice(); const index = clone.indexOf(value); if (index >= 0) { clone.splice(index, 1); } return clone; }; //Add Array const arrAdd = (list: Key[], value: Key) => { const clone = list.slice(); if (clone.indexOf(value) === -1) { clone.push(value); } return clone; }; //Position value to array const posToArr = (pos: string) => { return pos.split("-"); }; //Get Position const getPosition = (level: string | number, index: number) => { return `${level}-${index}`; }; //Judge Tree Node const isTreeNode = (node: NodeElement) => { return node && node.type && node.type.isTreeNode; }; //Get Drag Nodes keys const getDragNodesKeys = ( dragNodeKey: Key, keyEntities: Record ): Key[] => { const dragNodesKeys = [dragNodeKey]; const entity = keyEntities[dragNodeKey]; const dig = (list: DataEntity[] = []) => { list.forEach(({ key, children }) => { dragNodesKeys.push(key); dig(children); }); }; dig(entity.children); return dragNodesKeys; }; //Calc Drop Position, //Only used when drag, not affect SSR const calcDropPosition = (e: React.MouseEvent, treeNode: NodeInstance) => { const { clientY } = e; const { top, bottom, height } = treeNode.selectHandle.getBoundingClientRect(); const des = Math.max(height * DRAG_SIDE_RANGE, DRAG_MIN_GAP); if (clientY <= top + des) { return -1; } else if (clientY >= bottom - des) { return 1; } else { return 0; } }; /** * Return selectedKeys according with multiple props * @param selectedKeys * @param this.props * @return [string] */ const calcSelectedKeys = (selectedKeys: Key[], props: TreeProps) => { if (!selectedKeys) return undefined; const { multiple } = props; if (multiple) { return selectedKeys.slice(); } if (selectedKeys.length) { return [selectedKeys[0]]; } return selectedKeys; }; //Process Internal Props -- DataNode const internalProcessProps = (props: DataNode): Partial => props; //Convert Data Node to Tree Node Structure const convertDataToTree = ( treeData: DataNode[], processor?: { processProps: (prop: DataNode) => any } ): NodeElement[] => { if (!treeData) return []; const { processProps = internalProcessProps } = processor || {}; const list = Array.isArray(treeData) ? treeData : [treeData]; return list.map( ({ children, ...props }): NodeElement => { const childrenNodes = convertDataToTree(children, processor); return {childrenNodes}; } ); }; /** * If user use `autoExpandParent` we should get the list of parent node * @param keyList * @param keyEntities */ const conductExpandParent = ( keyList: Key[], keyEntities: Record ) => { const expandedKeys = {}; const conductUp = (key: Key) => { if (expandedKeys[key]) return; const entity = keyEntities[key]; if (!entity) return; expandedKeys[key] = true; const { parent, node } = entity; if (node.disabled) return; if (parent) { conductUp(parent.key); } }; (keyList || []).forEach(key => { conductUp(key); }); return Object.keys(expandedKeys); }; /** * Returns only the data- and aria- key/value paris */ const getDataAndAria = (props: Partial) => { const omitProps: Record = {}; Object.keys(props).forEach(key => { if (key.startsWith("data-") || key.startsWith("aria-")) { omitProps[key] = props[key]; } }); return omitProps; }; export { toArray, arrDel, arrAdd, posToArr, getPosition, isTreeNode, getDragNodesKeys, calcDropPosition, calcSelectedKeys, internalProcessProps, convertDataToTree, conductExpandParent, getDataAndAria };