song-ui-u
Version:
vue3 + js的PC前端组件库
203 lines (199 loc) • 6.69 kB
JavaScript
;
var vue = require('vue');
var column = require('./column.cjs');
var index = require('../../../hook/use-namespace/index.cjs');
require('song-ui-pro-icon');
require('../../../hook/use-zindex/index.cjs');
var table = /* @__PURE__ */ vue.defineComponent({
name: "x-table",
props: {
data: {
type: Array,
required: true
},
stripe: {
type: Boolean,
default: false
},
border: {
type: Boolean,
default: false
},
height: {
type: [String, Number],
default: "auto"
}
},
setup(props, {
slots,
emit
}) {
const ns = index.useNamespace("table");
const columns = vue.ref([]);
const selectedRows = vue.ref(/* @__PURE__ */ new Set());
const expandedRows = vue.ref(/* @__PURE__ */ new Set());
const indeterminateValue = vue.ref(false);
const getAllChildren = (row) => {
const children = [];
const stack = [row];
while (stack.length) {
const current = stack.pop();
if (current.children?.length) {
stack.push(...current.children);
children.push(...current.children);
}
}
return children;
};
const getParentRow = (row, data = props.data) => {
for (const item of data) {
if (item.children?.find((child) => child.id === row.id)) {
return item;
}
if (item.children?.length) {
const parent = getParentRow(row, item.children);
if (parent) return parent;
}
}
return null;
};
const handleSelect = (row) => {
const children = getAllChildren(row);
if (selectedRows.value.has(row)) {
selectedRows.value.delete(row);
children.forEach((child) => selectedRows.value.delete(child));
} else {
selectedRows.value.add(row);
children.forEach((child) => selectedRows.value.add(child));
}
let parent = getParentRow(row);
while (parent) {
const allChildren = getAllChildren(parent);
const allSelected = allChildren.every((child) => selectedRows.value.has(child));
if (allSelected) {
selectedRows.value.add(parent);
} else {
selectedRows.value.delete(parent);
}
parent = getParentRow(parent);
}
indeterminateValue.value = selectedRows.value.size > 0 && !isAllSelected.value;
emit("selection-change", Array.from(selectedRows.value));
};
const isSelected = (row) => {
return selectedRows.value.has(row);
};
if (slots.default) {
const children = slots.default();
columns.value = children.map((child) => ({
prop: child.props.prop,
label: child.props.label,
width: child.props.width || "auto",
slots: child?.children?.default,
align: child.props.align || "left",
type: child.props.type,
selectable: child.props.selectable || (() => true)
}));
}
const isAllSelected = vue.computed(() => {
const selectionColumn = columns.value.find((col) => col.type === "selection");
const getAllSelectableRows = (data) => {
let rows = [];
data.forEach((row) => {
if (selectionColumn?.selectable?.(row) ?? true) {
rows.push(row);
}
if (row.children?.length) {
rows = rows.concat(getAllSelectableRows(row.children));
}
});
return rows;
};
const selectableRows = getAllSelectableRows(props.data);
const selectedSelectableRows = Array.from(selectedRows.value).filter((row) => selectionColumn?.selectable?.(row) ?? true);
return selectableRows.length > 0 && selectedSelectableRows.length === selectableRows.length;
});
const handleSelectAll = (checked) => {
const processRow = (row) => {
if (checked) {
selectedRows.value.add(row);
} else {
selectedRows.value.delete(row);
}
row.children?.forEach(processRow);
};
props.data.forEach(processRow);
indeterminateValue.value = false;
emit("selection-change", Array.from(selectedRows.value));
};
const handleExpand = (row) => {
if (expandedRows.value.has(row.id)) {
expandedRows.value.delete(row.id);
} else {
expandedRows.value.add(row.id);
}
};
const isExpanded = (rowId) => expandedRows.value.has(rowId);
const renderRows = (data, level = 0) => {
const rows = [];
data.forEach((row, rowIndex) => {
rows.push(vue.createVNode("tr", {
"key": row.id,
"class": [ns.e("row"), ns.is("stripe", props.stripe && rowIndex % 2 === 0)]
}, [columns.value.map((column$1) => {
const Column = column.setColumn({
column: column$1,
row,
level,
columns: columns.value,
hasChildren: !!row.children?.length,
isExpanded: isExpanded(row.id),
onExpand: () => handleExpand(row),
getAllChildren,
isSelected,
onSelect: handleSelect,
isAllSelected,
onSelectAll: handleSelectAll,
indeterminate: indeterminateValue
});
return vue.createVNode("td", {
"class": [ns.e("cell"), ns.is("border", props.border)]
}, [vue.createVNode(Column, null, null)]);
})]));
if (row.children?.length && isExpanded(row.id)) {
rows.push(...renderRows(row.children, level + 1));
}
});
return rows;
};
return () => vue.createVNode("div", {
"class": [ns.b(), ns.is("border", props.border)],
"style": {
height: typeof props.height == "number" ? `${props.height}px` : props.height
}
}, [vue.createVNode("table", {
"class": [ns.e("container")]
}, [vue.createVNode("thead", {
"class": [ns.e("header")]
}, [vue.createVNode("tr", null, [columns.value.map((column$1) => {
const Column = column.setColumn({
column: column$1,
row: null,
columns: columns.value,
isAllSelected,
onSelectAll: handleSelectAll,
indeterminate: indeterminateValue
});
return vue.createVNode("th", {
"style": {
width: column$1.width + "px",
textAlign: column$1.align
},
"class": [ns.e("cell"), ns.is("border", props.border)],
"key": column$1.prop
}, [column$1.type === "selection" ? vue.createVNode(Column, null, null) : column$1.label]);
})])]), vue.createVNode("tbody", null, [renderRows(props.data)])])]);
}
});
module.exports = table;
//# sourceMappingURL=table.cjs.map