@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.
317 lines (316 loc) • 8.87 kB
JavaScript
import "../chunk-G2ADBYYC.js";
import { TreeStore } from "@opentiny/utils";
const close = ({ state, emit }) => () => {
state.search.show = false;
emit("update:visible", false);
emit("close", false);
};
const syncCheckStatus = ({ state, props, api }) => (value) => {
const { valueField, textField, modelValue: propsModelValue } = props;
const { lazy, isLeaf: leafField } = api.getNodeConfig();
let currentData;
let navList = [];
let modelValue = value || propsModelValue || [];
let len = modelValue.length;
let isLeaf;
for (let i = 0; i < len; i++) {
const id = modelValue[i];
currentData = state.store.getNode(id);
if (currentData) {
navList.push(currentData);
} else {
isLeaf = i === len - 1;
navList.push({
data: { [valueField]: id, [textField]: id, [leafField]: isLeaf },
loaded: false,
isLeaf,
childNodes: [],
level: i,
loading: false,
selfWaitLoad: true
});
}
}
state.isLeaf = !hasChildren(navList[len - 1]);
state.navList = navList;
state.level = lazy && state.waitLoadList.length ? 0 : Math.max(len - 1, 0);
};
const watchVisible = ({ emit, state, props, api }) => (visible) => {
const { modelValue } = props;
if (visible) {
api.watchModelValue(modelValue);
}
setTimeout(() => {
state.toggle = visible;
}, 0);
emit("update:visible", visible);
};
const watchModelValue = ({ props, state, emit }) => () => {
const { textSplit } = props;
emit("update:text", state.checkLabels.join(textSplit));
};
const hasChildren = (option) => option && !option.isLeaf;
const selectOption = ({ emit, state, props, api }) => (option) => {
const { valueField } = props;
const { lazy, load } = api.getNodeConfig();
const { navList, level, waitLoadList } = state;
const len = navList.length;
const appendNavList = () => {
const isSame = level < len && navList[level] === option;
if (!isSame) {
state.navList = [...navList.slice(0, level), option];
}
if (hasChildren(option)) {
state.level += 1;
}
state.isLeaf = !hasChildren(state.navList[state.navList.length - 1]);
emit("node-expand", option);
};
if (lazy && load && (option.selfWaitLoad || !option.loaded && !option.isLeaf)) {
option.loading = true;
state.loading = true;
load(option, (nodes) => {
let index, node;
option.loading = false;
state.loading = false;
option.loaded = true;
nodes.forEach((data) => {
state.store.append(data, option.data);
index = waitLoadList.indexOf(data[valueField]);
if (index !== -1) {
node = state.store.getNode(data);
state.navList = state.navList.map((option2) => {
if (node && option2.data[valueField] === data[valueField]) {
option2 = node;
}
return option2;
});
}
});
appendNavList();
});
} else {
appendNavList();
}
emit("click", option);
};
const confirm = ({ emit, state, api }) => () => {
if (state.search.show) {
api.searchBoxToggle(false);
} else {
emit("confirm", state);
emit("update:visible", false);
emit("update:modelValue", state.checkIds);
}
};
const loopSearchOption = ({
options,
input,
childrenField,
valueField,
textField,
prefixValue,
prefixText,
textSplit = "/",
filterMethod,
level,
checkStrictly
}) => {
const list = [];
options.forEach((item) => {
if (item.disabled) {
return;
}
const text = item[textField];
const textNavStr = prefixText ? prefixText + textSplit + text : text;
const value = [...prefixValue, item[valueField]];
const children = item[childrenField];
if (checkStrictly === true || !children || children.length === 0) {
if (typeof filterMethod === "function") {
const matched = filterMethod({ data: item, label: item.label, value: item.value, level }, input);
if (matched) {
list.push({
[valueField]: value,
[textField]: textNavStr
});
}
} else if (text.includes(input)) {
list.push({
[valueField]: value,
[textField]: textNavStr
});
}
}
if (children && children.length) {
const arr = loopSearchOption({
options: children,
input,
childrenField,
valueField,
textField,
prefixValue: value,
prefixText: textNavStr,
textSplit,
filterMethod,
level: level + 1,
checkStrictly
});
list.push(...arr);
}
});
return list;
};
const searchMethod = ({ state, props, api }) => () => {
const { searchConfig, valueField, textField } = props;
const { children: childrenField } = api.getNodeConfig();
const { input, options } = state.search;
let list = [];
if (searchConfig && searchConfig.searchMethod) {
list = searchConfig.searchMethod({ input, options, state }) || [];
} else if (input) {
list = loopSearchOption({
options,
input,
childrenField,
valueField,
textField,
prefixValue: [],
prefixText: "",
filterMethod: searchConfig.filterMethod,
level: 0,
checkStrictly: props.nodeConfig.checkStrictly
});
}
if (typeof list.then === "function") {
list.then((data) => state.search.filterOptions = data);
} else {
state.search.filterOptions = list;
}
};
const searchBoxToggle = ({ state, props, api }) => (isShow) => {
const { searchConfig = {} } = props;
const { lazy } = api.getNodeConfig();
state.search.show = isShow;
state.search.input = "";
if (isShow) {
state.search.options = !lazy && searchConfig.options && searchConfig.options.length ? searchConfig.options : state.store.getAllData();
api.searchMethod();
}
};
const searchSelectHandler = ({ emit, api, props }) => (option) => {
const { valueField } = props;
api.searchBoxToggle(false);
api.syncCheckStatus(option[valueField]);
emit("search-click", option);
};
const isSelected = ({ state }) => (option) => {
const { navList } = state;
return navList.includes(option);
};
const setLevel = ({ state, api }) => (level, option) => {
if (!api.disabledNavOption(level, option)) {
state.level = level;
}
};
const created = ({ api }) => () => {
api.initTreeStore();
};
const loadData = ({ props, state }) => (data) => {
if (!props.visible) {
return;
}
state.store.setData(data);
};
const renderSearchOption = ({ state }) => (text) => {
return (text || "").split(state.search.input);
};
const computedNavListHandler = ({ state, props }) => () => {
const { textField, placeholder } = props;
const { isLeaf, navList } = state;
const placeholderArr = [];
const len = navList.length;
if (!Array.isArray(placeholder)) {
placeholderArr.push({ data: { [textField]: placeholder }, selfWaitLoad: true });
} else if (len < placeholder.length) {
for (let i = len; i < placeholder.length; i++) {
placeholderArr.push({ data: { [textField]: placeholder[i] }, selfWaitLoad: true });
}
}
return isLeaf && len ? state.navList : [...state.navList, ...placeholderArr];
};
const disabledNavOption = ({ state }) => (level, option) => {
const node = state.navList[level - 1];
return option.selfWaitLoad && (!node || !node.childNodes.length);
};
const getNodeConfig = ({ constants, props }) => () => {
const { nodeConfig, valueField } = props;
return Object.assign({ nodeKey: valueField }, constants.defaultNodeConfig, nodeConfig);
};
const initTreeStore = ({ props, state, api }) => () => {
const { data, textField } = props;
const {
nodeKey,
lazy,
load,
afterLoad,
children,
isLeaf,
checkStrictly,
currentNodeKey,
checkDescendants,
defaultCheckedKeys,
defaultExpandedKeys,
autoExpandParent,
defaultExpandAll,
filterNodeMethod
} = api.getNodeConfig();
state.store = new TreeStore({
key: nodeKey,
data,
lazy,
props: {
children,
label: textField,
isLeaf
},
load,
afterLoad: () => {
state.rootData = state.root.childNodes || [];
api.syncCheckStatus();
afterLoad && afterLoad();
},
currentNodeKey,
checkStrictly,
checkDescendants,
defaultCheckedKeys,
defaultExpandedKeys,
autoExpandParent,
defaultExpandAll,
filterNodeMethod
});
state.root = state.store.root;
if (!lazy) {
state.rootData = state.root.childNodes || [];
api.syncCheckStatus();
}
};
export {
close,
computedNavListHandler,
confirm,
created,
disabledNavOption,
getNodeConfig,
initTreeStore,
isSelected,
loadData,
renderSearchOption,
searchBoxToggle,
searchMethod,
searchSelectHandler,
selectOption,
setLevel,
syncCheckStatus,
watchModelValue,
watchVisible
};