various-ui
Version:
This is a test version of the Vue 3 component library
262 lines (259 loc) • 8.7 kB
JavaScript
import { reactive, ref, shallowRef, watch, nextTick } from 'vue';
import gsap from 'gsap';
const useComposable = (define, emits) => {
const refs = {
sorts: reactive({ key: "", value: "" }),
//* 排序数据
selects: ref([]),
//* 选择数据
childrens: ref([])
//* 嵌套数据
};
const nodes = {
head: ref(),
main: ref(),
bodys: ref([]),
container: ref()
};
const variable = {
size: 0,
observer: shallowRef()
};
const disposable = {
//* 表格内容属性
body: (data, index) => {
if (refs.selects.value.includes(index) || refs.childrens.value.includes(index)) {
return { class: "ui-active" };
}
return {};
},
//* 表头额外控件属性
extra: (data) => {
return {
"align": "center",
"trigger": "click",
"direction": "bottom",
"class-extra-name": data["extra-name"]
};
},
//* 表格内容对齐属性
align: (data) => {
switch (data.align) {
case "singularity":
return { "justify-content": "center", "text-align": "left" };
case "center":
return { "justify-content": "center", "text-align": "center" };
case "right":
return { "justify-content": "flex-end", "text-align": "right" };
default:
return { "justify-content": "flex-start", "text-align": "left" };
}
}
};
const methods = {
//* 初始化函数
init: () => {
var _a, _b;
if (!nodes.container.value || !nodes.main.value || !nodes.head.value) return;
else {
nodes.container.value.querySelectorAll(":scope>div").forEach((node) => node.style.width = "");
}
const rows = [nodes.head.value, ...nodes.bodys.value];
const vars = {
replenish: 0,
size: Math.floor(nodes.head.value.clientWidth) - 4,
//! 这里-4是预留宽度,用于解决因小数点计算导致的尺寸偏差
data: []
};
if (vars.size <= 0) return;
define.option.forEach((value) => {
const result = {
key: value.key,
min: value["min-width"] || 0,
max: value["max-width"] || 0,
width: value.width || value["min-width"] || 0,
replenish: !value.width
};
if (!value.width) {
rows.forEach((row) => {
const node = row.querySelector(`.ui-table2-column[name=${value.key}]`);
const context = node.firstElementChild;
if (!node) return;
else {
node.style.whiteSpace = "nowrap";
node.style.width = "";
if (context) {
context.style.width = "";
}
if (node.clientWidth > result.width) {
if (result.max && node.clientWidth > result.max) {
result.width = result.max;
} else {
result.width = Math.ceil(node.clientWidth) + 4;
}
}
node.style.whiteSpace = "";
}
});
}
vars.data.push(result);
});
const real = vars.data.reduce((former, current) => {
return former + current.width;
}, 0);
if (!define.overflow || define.overflow && vars.size >= real) {
vars.replenish = vars.size - real;
while (Math.floor(Math.abs(vars.replenish)) != 0) {
const data = vars.data.filter((val) => {
return val.replenish && (vars.replenish > 0 ? !val.max || val.width < val.max : !val.min || val.width > val.min);
});
if (!data.length || vars.replenish / data.length == 0) break;
if (vars.replenish > 0) {
const replenish = vars.replenish / data.length;
data.forEach((value) => {
if (value.max && value.width + replenish > value.max) {
vars.replenish -= value.max - value.width;
value.width = value.max;
} else {
value.width += replenish;
vars.replenish -= replenish;
}
});
} else if (vars.replenish < 0) {
const max = ((_b = (_a = data.sort((a, b) => b.width - a.width)) == null ? void 0 : _a[0]) == null ? void 0 : _b.width) || 0;
for (let i = 0; i < data.length; i++) {
if (vars.replenish == 0) break;
if (data[i].width == max && data[i].width > data[i].min) {
if (data[i].min && data[i].width - 1 < data[i].min) {
vars.replenish += data[i].width - data[i].min;
data[i].width = data[i].min;
} else {
vars.replenish += 1;
data[i].width -= 1;
}
}
}
}
}
} else {
const size = real + Math.ceil(nodes.container.value.clientWidth - nodes.head.value.clientWidth) + 4;
nodes.container.value.querySelectorAll(":scope>div").forEach((node) => {
node.style.width = size + "px";
});
}
vars.data.forEach((value) => {
rows.forEach((row) => {
const node = row.querySelector(`.ui-table2-column[name=${value.key}]`);
if (!node) return;
else {
node.style.width = value.width + "px";
}
});
});
define.option.filter((value) => value.align == "singularity").forEach((value) => {
let result = 0;
nodes.bodys.value.forEach((row) => {
const node = row.querySelector(`.ui-table2-column[name=${value.key}] > .ui-table2-context`);
if (!node) return;
else {
result = Math.max(result, node.offsetWidth);
}
});
nodes.bodys.value.forEach((row) => {
const node = row.querySelector(`.ui-table2-column[name=${value.key}] > .ui-table2-context`);
if (node && node.offsetWidth >= result) return;
else {
node.style.width = result + "px";
}
});
});
},
//* 排序
sort: (data) => {
if (!data) {
refs.sorts.key = "";
refs.sorts.value = "";
} else {
if (refs.sorts.key != data.key) {
refs.sorts.key = data.key;
refs.sorts.value = "asc";
} else {
if (refs.sorts.value == "asc") {
refs.sorts.value = "desc";
} else {
refs.sorts.key = "";
refs.sorts.value = "";
}
}
emits("sort", refs.sorts);
}
},
//* 单选
radio: (index) => {
if (index == void 0) refs.selects.value = [];
else {
refs.selects.value = [index];
emits("radio", define.data[index]);
}
},
//* 选择
select: (index) => {
if (define.selector == "checkbox") methods.checkbox(index);
else if (define.selector == "children") methods.children(index);
else if (define.selector == "radio") {
methods.radio(index);
}
},
//* 多选
checkbox: (index) => {
if (index == void 0) refs.selects.value = [];
else {
const key = refs.selects.value.findIndex((value) => value == index);
if (key != -1) {
refs.selects.value.splice(key, 1);
} else {
refs.selects.value.push(index);
}
const result = refs.selects.value.map((index2) => define.data[index2]);
emits("checkbox", result);
}
},
//* 嵌套
children: (index, callBack) => {
if (index == void 0) refs.childrens.value = [];
else {
const key = refs.childrens.value.findIndex((value) => value == index);
if (key != -1) {
refs.childrens.value.splice(key, 1);
callBack && callBack(false);
} else {
refs.childrens.value.push(index);
callBack && callBack(true);
}
}
}
};
const watchs = {
watch_stop: watch(
() => define.data,
() => {
refs.selects.value = [];
refs.childrens.value = [];
nextTick(() => methods.init());
}
)
};
const ons = {
animation: {
//* 动画(入场前)
"before-enter": (el) => gsap.set(el, { height: 0, opacity: 0 }),
//* 动画(离场)
"leave": (el, onComplete) => gsap.to(el, { height: 0, opacity: 0, duration: 0.2, onComplete }),
//* 动画(入场)
"enter": (el, onComplete) => gsap.to(el, { height: "auto", opacity: 1, duration: 0.2, onComplete })
}
};
return { ons, refs, nodes, watchs, methods, variable, disposable };
};
export { useComposable };
//# sourceMappingURL=composable.mjs.map