diff --git a/example/cypress/support/e2e.ts b/example/cypress/support/e2e.ts index 3d469a6b..84e96a51 100644 --- a/example/cypress/support/e2e.ts +++ b/example/cypress/support/e2e.ts @@ -15,3 +15,12 @@ // Import commands.js using ES2015 syntax: import './commands'; + +Cypress.on('uncaught:exception', (e) => { + if ( + /ResizeObserver loop completed/.test(e.message) || + /ResizeObserver loop limit exceeded/.test(e.message) + ) { + return false; + } +}); diff --git a/src/components/tables/TableHead.vue b/src/components/tables/TableHead.vue index 7e8cdcc0..b81f704c 100644 --- a/src/components/tables/TableHead.vue +++ b/src/components/tables/TableHead.vue @@ -127,14 +127,14 @@ const onToggleAll = (checked: boolean) => emit('select:all', checked); const isSortedBy = (key: TableColumn['key']) => key in props.sortedMap; -const getSortIndex = (key: TableColumn['key']) => { +const getSortIndex = (key: TableColumn['key']): number => { const sortBy = props.sortData; if (!sortBy || !Array.isArray(sortBy) || !isSortedBy(key)) { return -1; } - return sortBy.findIndex((sort) => sort.column === key) ?? -1; + return sortBy.findIndex((sort) => sort.column === key); }; const getSortDirection = (key: TableColumn['key']) => @@ -182,7 +182,7 @@ const getSortDirection = (key: TableColumn['key']) => = ref(0)) => { +export const useStickyTableHeader = ( + offsetTop: Ref = ref(0), + sticky: Ref = ref(false), +) => { const table: Ref = ref(null); const tableScroller: Ref = ref(null); const stick: Ref = ref(false); @@ -15,10 +18,10 @@ export const useStickyTableHeader = (offsetTop: Ref = ref(0)) => { row: ':scope > tbody > tr:not([hidden])', }; - const updateHeaderCellWidth = () => { + const watchCellWidth = () => { const root = get(table); - if (!root) { + if (!get(sticky) || !root) { return; } @@ -28,22 +31,29 @@ export const useStickyTableHeader = (offsetTop: Ref = ref(0)) => { const head: HTMLHeadElement | null = root.querySelector(selectors.head) ?? null; + const columns: NodeListOf | undefined = head?.querySelectorAll( selectors.th, ); + const clonedColumns: NodeListOf | undefined = theadClone?.querySelectorAll(selectors.th); - columns?.forEach((column: HTMLElement, i: number) => { - const cellRect = clonedColumns?.item(i)?.getBoundingClientRect(); - column.style.width = `${cellRect?.width ?? 0}px`; + clonedColumns?.forEach((th: HTMLElement, i: number) => { + useResizeObserver(th, (entries) => { + const cellRect = entries[0].target.getBoundingClientRect(); + const column = columns?.item(i); + if (column) { + column.style.width = `${cellRect.width}px`; + } + }); }); }; - const addStickyClass = () => { + const toggleStickyClass = () => { const root = get(table); - if (!root) { + if (!get(sticky) || !root) { return; } @@ -73,7 +83,6 @@ export const useStickyTableHeader = (offsetTop: Ref = ref(0)) => { const top = get(offsetTop) ?? 0; head.style.width = `${theadWidth}px`; - theadClone.style.height = `${headRect.height}px`; const rows = root.querySelectorAll(selectors.row); @@ -98,29 +107,12 @@ export const useStickyTableHeader = (offsetTop: Ref = ref(0)) => { } }; - const updateHeader = () => { - addStickyClass(); - updateHeaderCellWidth(); - }; - - watchEffect(() => { - if (!get(table)?.querySelector(selectors.head)) { - return; - } - - updateHeader(); - - const scroller = get(tableScroller); - - if (scroller) { - useResizeObserver(get(tableScroller), updateHeader); - } - }); - onMounted(() => { - useEventListener(window, 'scroll', addStickyClass); - useEventListener(window, 'resize', updateHeader); - useEventListener(tableScroller, 'scroll', updateHeader); + toggleStickyClass(); + useEventListener(tableScroller, 'scroll', toggleStickyClass); + useEventListener(document.body, 'scroll', toggleStickyClass); + useEventListener(window, 'resize', toggleStickyClass); + watchCellWidth(); }); return {