vuestic-ui
Version:
Vue 3 UI Framework
112 lines (111 loc) • 3.19 kB
JavaScript
import { computed, watchEffect } from "vue";
import { u as useEvent } from "../useEvent.js";
import { u as useElementBackground } from "../useElementBackground.js";
const syncTh = (thead1, thead2) => {
const ths1 = thead1.querySelectorAll("th");
const ths2 = thead2.querySelectorAll("th");
ths1.forEach((th, index) => {
const th2 = ths2[index];
th2.style.width = `${th.getBoundingClientRect().width}px`;
});
};
const recursiveGetOffset = (el, offset = 0) => {
if (!el) {
return offset;
}
return recursiveGetOffset(el.offsetParent, offset + el.offsetTop);
};
const useStickyTableHeaders = (tableEl, offset = 0) => {
let mutationObserver = null;
let headClone = null;
let head = null;
let table = null;
let headOffset = 0;
let hasTransform = false;
let tableHeight = 0;
let headHeight = 0;
const htmlTable = computed(() => {
if (!tableEl.value) {
return null;
}
const el = "$el" in tableEl.value ? tableEl.value.$el : tableEl.value;
return el.tagName === "TABLE" ? el : el.querySelector("table");
});
const htmlTableHead = computed(() => {
if (!htmlTable.value) {
return null;
}
return htmlTable.value.querySelector("thead");
});
const bg = useElementBackground(htmlTableHead);
watchEffect(() => {
if (!tableEl.value) {
return;
}
const rootEl = htmlTable.value;
if (!rootEl) {
return;
}
table = htmlTable.value;
head = htmlTableHead.value;
if (!head) {
return;
}
table.style.position = "relative";
headClone = head.cloneNode(true);
headClone.style.position = "fixed";
headClone.style.top = "0px";
headClone.style.width = `${table.clientWidth}px`;
headClone.style.zIndex = "1";
headClone.style.backgroundColor = bg.value;
headClone.style.display = "none";
table.appendChild(headClone);
syncTh(head, headClone);
headOffset = recursiveGetOffset(head);
hasTransform = window.getComputedStyle(table).transform !== "none";
tableHeight = table.clientHeight;
headHeight = head.clientHeight;
mutationObserver = new MutationObserver(() => {
if (!headClone) {
return;
}
if (!head) {
return;
}
if (!table) {
return;
}
headClone.style.width = `${table.clientWidth}px`;
syncTh(head, headClone);
headOffset = recursiveGetOffset(head);
tableHeight = table.clientHeight;
headHeight = head.clientHeight;
});
mutationObserver.observe(table, {
childList: true,
subtree: true,
attributes: true
});
});
useEvent("scroll", () => {
if (!headClone) {
return;
}
const y = window.scrollY;
if (y > headOffset - offset && y < headOffset + tableHeight - offset - headHeight) {
headClone.style.display = "block";
if (hasTransform) {
headClone.style.top = `${y - headOffset + offset - 2}px`;
} else {
headClone.style.top = `${offset}px`;
}
} else {
headClone.style.top = "0px";
headClone.style.display = "none";
}
});
};
export {
useStickyTableHeaders as u
};
//# sourceMappingURL=useStickyTableHeaders.js.map