UNPKG

@opentiny/vue-renderless

Version:

An enterprise-class UI component library, support both Vue.js 2 and Vue.js 3, as well as PC and mobile.

302 lines (301 loc) 9.32 kB
import "../chunk-G2ADBYYC.js"; import { isNull } from "@opentiny/utils"; import { isEqual } from "@opentiny/utils"; import { isEmpty } from "../cascader"; import { KEY_CODE, CASCADER } from "@opentiny/utils"; import { scrollIntoView as scrollIntoViewCommon } from "@opentiny/utils"; const watchCheckedValue = ({ api, emit, props, state }) => (value) => { if (!isEqual(value, props.modelValue)) { state.checkStrictly && api.calculateCheckedNodePaths(); emit("update:modelValue", value); emit("change", value); } }; const initStore = ({ api, props, state, Store }) => () => { if (state.config.lazy && isEmpty(props.options)) { api.lazyLoad(); } else { state.store = new Store(props.options, state.config); state.menus = [state.store.getNodes()]; api.syncMenuState(); } }; const syncCheckedValue = ({ api, props, state }) => () => { if (!isEqual(props.modelValue, state.checkedValue)) { state.checkedValue = props.modelValue; api.syncMenuState(); } }; const syncMenuState = ({ api, nextTick, state }) => () => { api.syncActivePath(); state.multiple && api.syncMultiCheckState(); state.checkStrictly && api.calculateCheckedNodePaths(); nextTick(() => api.scrollIntoView); }; const syncMultiCheckState = ({ api, state }) => () => { const nodes = api.getFlattedNodes(state.leafOnly); nodes.forEach((node) => { if (state.checkedValue) { node.syncCheckState(state.checkedValue); } }); }; const syncActivePath = ({ api, state }) => () => { if (!isEmpty(state.activePath)) { const nodes = state.activePath.map((node) => api.getNodeByValue(node.getValue())).filter((node) => node); if (isNull(nodes[0])) { state.activePath = []; } else { api.expandNodes(nodes); } } else if (!isEmpty(state.checkedValue)) { const value = state.multiple ? state.checkedValue[0] : state.checkedValue; const checkedNode = api.getNodeByValue(value) || {}; const nodes = (checkedNode.pathNodes || []).slice(0, -1); api.expandNodes(nodes); } else { state.activePath = []; state.menus = [state.store.getNodes()]; } }; const expandNodes = (api) => (nodes) => nodes.forEach((node) => api.handleExpand(node, true)); const coerceTruthyValueToArray = (val) => { if (Array.isArray(val)) { return val; } else if (val) { return [val]; } return []; }; const calculateCheckedNodePaths = ({ api, state }) => () => { const checkedValues = state.multiple ? coerceTruthyValueToArray(state.checkedValue) : [state.checkedValue]; state.checkedNodePaths = checkedValues.map((v) => { const checkedNode = api.getNodeByValue(v); return checkedNode ? checkedNode.pathNodes : []; }); }; const focusNode = (api) => (el) => { if (!el) { return; } el.focus(); !api.isLeaf(el) && el.click(); }; const getMenuIndex = () => (el) => { if (!el) { return; } const pieces = el.id.split("-"); return Number(pieces[pieces.length - 2]); }; const checkNode = (api) => (el) => { if (!el) { return; } const input = el.querySelector("input"); if (input) { input.click(); } else if (api.isLeaf(el)) { el.click(); } }; const handleKeyDown = ({ api, emit, menus }) => (event) => { const { target, keyCode } = event; if (keyCode === KEY_CODE.ArrowUp) { const prev = getSibling(target, -1); api.focusNode(prev); } else if (keyCode === KEY_CODE.ArrowDown) { const next = getSibling(target, 1); api.focusNode(next); } else if (keyCode === KEY_CODE.ArrowLeft) { const preMenu = menus[Number(api.getMenuIndex(target)) - 1]; if (preMenu) { const expandedNode = preMenu.$el.querySelector(CASCADER.CascaderNodeExpand); api.focusNode(expandedNode); } } else if (keyCode === KEY_CODE.ArrowRight) { const nextMenu = menus[Number(api.getMenuIndex(target)) + 1]; if (nextMenu) { const firstNode = nextMenu.$el.querySelector(CASCADER.CascaderNodeTab); api.focusNode(firstNode); } } else if (keyCode === KEY_CODE.Enter) { api.checkNode(target); } else if (~[KEY_CODE.Escape, KEY_CODE.Tab].indexOf(keyCode)) { emit("close"); } }; const handleExpand = ({ emit, state }) => (node, silent) => { const { level } = node; const path = state.activePath.slice(0, level - 1); const menus = state.menus.slice(0, level); if (!node.isLeaf) { path.push(node); menus.push(node.children); } state.activePath = path; state.menus = menus; if (!silent) { const pathValues = path.map((node2) => node2.getValue()); emit("active-item-change", pathValues); emit("expand-change", pathValues); } }; const handleCheckChange = (state) => (value) => { state.checkedValue = value; }; const lazyLoad = ({ api, $parent, state, Store, emit }) => (currentNode, onFullfiled) => { let node = currentNode; if (!node) { node = node || { root: true, level: 0 }; state.store = new Store([], state.config); state.menus = [state.store.getNodes()]; } node.loading = true; const afterLoad = (dataList) => { const parent = node.root ? null : node; dataList && dataList.length && state.store.appendNodes(dataList, parent); node.loading = false; node.loaded = true; emit("load-data", dataList); if (Array.isArray(state.checkedValue)) { const nodeValue = state.checkedValue[state.loadCount++]; const valueKey = state.config.value; const leafKey = state.config.leaf; if (Array.isArray(dataList) && dataList.filter((item) => item[valueKey] === nodeValue).length > 0) { const checkedNode = state.store.getNodeByValue(nodeValue); if (!(checkedNode == null ? void 0 : checkedNode.data[leafKey])) { api.lazyLoad(checkedNode, () => { api.handleExpand(checkedNode); }); } if ($parent.computePresentText && state.loadCount === state.checkedValue.length) { $parent.computePresentText(); } } } onFullfiled && onFullfiled(dataList); }; state.config.lazyLoad(node, afterLoad); }; const calculateMultiCheckedValue = ({ api, state }) => () => { state.checkedValue = api.getCheckedNodes(state.leafOnly).map((node) => node.getValueByOption()); }; const scrollIntoView = ({ menus }) => () => { menus.forEach((menu) => { const menuElement = menu.$el; if (menuElement) { const container = menuElement.querySelector(CASCADER.ScrollWrap); const activeNode = menuElement.querySelector(CASCADER.CascaderActice) || menuElement.querySelector(CASCADER.ActivePath); scrollIntoViewCommon(container, activeNode); } }); }; const getNodeByValue = (state) => (val) => state.store.getNodeByValue(val); const getFlattedNodes = (state) => (leafOnly) => { const cached = !state.config.lazy; return state.store.getFlattedNodes(leafOnly, cached); }; const getCheckedNodes = ({ api, state }) => (leafOnly, cascaderCheckedValue) => { const isCascaderChecked = (str, checkedValue) => { let flag = true; if (!state.multiple || !checkedValue) { return flag; } flag = false; if (!Array.isArray(checkedValue)) { return flag; } for (let i = 0; i < checkedValue.length; i++) { if (Array.isArray(checkedValue[i])) { if (checkedValue[i].length) { flag = checkedValue[i][checkedValue[i].length - 1] === str; } } else { flag = checkedValue[i] === str; } if (flag) { break; } } return flag; }; if (state.multiple) { const nodes = api.getFlattedNodes(leafOnly); return nodes.filter((node2) => node2.checked && isCascaderChecked(node2.value, cascaderCheckedValue)); } const node = api.getNodeByValue(cascaderCheckedValue || state.checkedValue); return isEmpty(state.checkedValue) || !node ? [] : [node]; }; const clearCheckedNodes = ({ api, state }) => () => { const { multiple, emitPath } = state.config; if (multiple) { api.getCheckedNodes(state.leafOnly).filter((node) => !node.isDisabled).forEach((node) => node.doCheck(false)); api.calculateMultiCheckedValue(); } else { state.checkedValue = emitPath ? [] : null; } }; const isLeaf = () => (el) => !el.getAttribute("data-owns"); const getSibling = (el, distance) => { const { parentNode } = el; if (parentNode) { const siblings = parentNode.querySelectorAll(CASCADER.CascaderNodeTab); const index = Array.prototype.indexOf.call(siblings, el); return siblings[index + distance] || null; } return null; }; const valueEquals = (a, b) => { if (a === b) { return true; } if (!Array.isArray(b)) { return false; } if (!Array.isArray(a)) { return false; } if (a.length !== b.length) { return false; } for (let i = 0, len = a.length; i !== len; ++i) { if (a[i] !== b[i]) { return false; } } return true; }; export { calculateCheckedNodePaths, calculateMultiCheckedValue, checkNode, clearCheckedNodes, coerceTruthyValueToArray, expandNodes, focusNode, getCheckedNodes, getFlattedNodes, getMenuIndex, getNodeByValue, getSibling, handleCheckChange, handleExpand, handleKeyDown, initStore, isLeaf, lazyLoad, scrollIntoView, syncActivePath, syncCheckedValue, syncMenuState, syncMultiCheckState, valueEquals, watchCheckedValue };