@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
JavaScript
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
};