|
1 | 1 | <script lang="ts">
|
2 |
| - import { createEventDispatcher } from 'svelte'; |
| 2 | + import { afterUpdate, onDestroy, createEventDispatcher } from 'svelte'; |
3 | 3 | import { readable, writable } from 'svelte/store';
|
4 | 4 |
|
5 | 5 | import Fa from 'svelte-fa';
|
|
80 | 80 | const actionDispatcher = (obj) => dispatch('action', obj);
|
81 | 81 |
|
82 | 82 | // Stores to hold the width and height information for resizing
|
83 |
| - const rowHeights = writable< |
84 |
| - { |
85 |
| - max: number; |
86 |
| - min: number; |
87 |
| - }[] |
88 |
| - >([]); |
| 83 | + const rowHeights = writable<{ [key: number]: { max: number; min: number } }>({}); |
89 | 84 | const colWidths = writable<number[]>([]);
|
90 | 85 |
|
91 | 86 | // Server-side variables
|
|
392 | 387 | const getMaxCellHeightInRow = () => {
|
393 | 388 | if (!tableRef || resizable === 'columns' || resizable === 'none') return;
|
394 | 389 |
|
395 |
| - // Initialize the rowHeights array if it is empty |
396 |
| - if ($rowHeights.length === 0) { |
397 |
| - $rowHeights = Array.from({ length: $pageRows.length }, () => ({ max: 44, min: 20 })); |
398 |
| - } |
399 |
| -
|
400 | 390 | tableRef.querySelectorAll('tbody tr').forEach((row, index) => {
|
401 | 391 | const cells = row.querySelectorAll('td');
|
402 | 392 |
|
|
415 | 405 | });
|
416 | 406 |
|
417 | 407 | rowHeights.update((rh) => {
|
418 |
| - rh[index].max = maxHeight - 24; |
419 |
| - rh[index].min = Math.max(minHeight - 24, rowHeight ?? 20); |
420 |
| - return rh; |
| 408 | + const id = +row.id.split(`${tableId}-row-`)[1]; |
| 409 | + return { |
| 410 | + ...rh, |
| 411 | + [id]: { |
| 412 | + max: maxHeight - 24, |
| 413 | + min: Math.max(minHeight - 24, rowHeight ?? 20) |
| 414 | + } |
| 415 | + }; |
421 | 416 | });
|
422 | 417 | });
|
423 | 418 | };
|
|
431 | 426 | }
|
432 | 427 |
|
433 | 428 | colWidths.update((cw) => {
|
434 |
| - tableRef.querySelectorAll('thead tr th span').forEach((cell, index) => { |
| 429 | + tableRef?.querySelectorAll('thead tr th span').forEach((cell, index) => { |
435 | 430 | // + 12 pixels for padding and + 32 pixels for filter icon
|
436 | 431 | // If the column width is 100, which means it has not been initialized, then calculate the width
|
437 | 432 | cw[index] = cw[index] === 100 ? cell.getBoundingClientRect().width + 12 + 32 : cw[index];
|
|
440 | 435 | });
|
441 | 436 | };
|
442 | 437 |
|
443 |
| - const resizeObserver = new ResizeObserver(() => { |
| 438 | + const resizeRowsObserver = new ResizeObserver(() => { |
444 | 439 | getMaxCellHeightInRow();
|
| 440 | + }); |
| 441 | +
|
| 442 | + const resizeColumnsObserver = new ResizeObserver(() => { |
445 | 443 | getMinCellWidthInColumn();
|
446 | 444 | });
|
447 | 445 |
|
448 | 446 | const observeFirstCells = () => {
|
449 | 447 | if (!tableRef) return;
|
450 | 448 |
|
| 449 | + $pageRows.forEach((row) => { |
| 450 | + const cell = tableRef.querySelector(`#${tableId}-row-${row.id}`); |
| 451 | + if (cell) { |
| 452 | + resizeRowsObserver.observe(cell); |
| 453 | + } |
| 454 | + }); |
| 455 | +
|
451 | 456 | tableRef.querySelectorAll('tbody tr td:first-child').forEach((cell) => {
|
452 |
| - resizeObserver.observe(cell); |
| 457 | + resizeRowsObserver.observe(cell); |
453 | 458 | });
|
454 | 459 | };
|
455 | 460 |
|
456 | 461 | const observeHeaderColumns = () => {
|
457 | 462 | if (!tableRef) return;
|
458 | 463 |
|
459 | 464 | tableRef.querySelectorAll('thead tr th').forEach((cell) => {
|
460 |
| - resizeObserver.observe(cell); |
| 465 | + resizeColumnsObserver.observe(cell); |
461 | 466 | });
|
462 | 467 | };
|
463 | 468 |
|
| 469 | + afterUpdate(() => { |
| 470 | + if (resizable !== 'rows' && resizable !== 'both') { |
| 471 | + return; |
| 472 | + } |
| 473 | + // Making sure tableRef is up to date and contains the new rows |
| 474 | + // If it contains even one element, it means it contains them all |
| 475 | + const e = tableRef?.querySelector(`#${tableId}-row-${$pageRows[0].id}`); |
| 476 | + if (e) { |
| 477 | + getDimensions(); |
| 478 | + } |
| 479 | + }); |
| 480 | +
|
| 481 | + // Remove the resize observer when the component is destroyed for performance reasons |
| 482 | + onDestroy(() => { |
| 483 | + resizeRowsObserver.disconnect(); |
| 484 | + resizeColumnsObserver.disconnect(); |
| 485 | + }); |
| 486 | +
|
464 | 487 | const getDimensions = () => {
|
| 488 | + if (!tableRef) return; |
465 | 489 | if (resizable === 'none') return;
|
466 | 490 | else if (resizable === 'columns') {
|
467 | 491 | observeHeaderColumns();
|
|
477 | 501 | $: serverSide && updateTable();
|
478 | 502 | $: serverSide && sortServer($sortKeys[0]?.order, $sortKeys[0]?.id);
|
479 | 503 | $: $hiddenColumnIds = shownColumns.filter((col) => !col.visible).map((col) => col.id);
|
480 |
| - $: tableRef && getDimensions(); |
481 |
| - $: $headerRows.length > 0 && getMinCellWidthInColumn(); |
482 |
| - $: $pageRows.length > 0 && getMaxCellHeightInRow(); |
483 | 504 | </script>
|
484 | 505 |
|
485 | 506 | <div class="grid gap-2 overflow-auto" class:w-fit={!fitToScreen} class:w-full={fitToScreen}>
|
|
682 | 703 | class=" h-full {index === 0 &&
|
683 | 704 | (resizable === 'rows' || resizable === 'both')
|
684 | 705 | ? 'resize-y overflow-auto'
|
685 |
| - : ''}" |
| 706 | + : 'block'}" |
686 | 707 | id="{tableId}-{cell.id}-{row.id}"
|
687 | 708 | style={`
|
688 |
| - min-height: ${$rowHeights && $rowHeights[row.id] ? `${$rowHeights[row.id].min}px` : 'auto'}; |
| 709 | + min-height: ${$rowHeights && $rowHeights[+row.id] ? `${$rowHeights[+row.id].min}px` : 'auto'}; |
689 | 710 | max-height: ${
|
690 |
| - index !== 0 && $rowHeights && $rowHeights[row.id] |
691 |
| - ? `${$rowHeights[row.id].max}px` |
| 711 | + index !== 0 && $rowHeights && $rowHeights[+row.id] |
| 712 | + ? `${$rowHeights[+row.id].max}px` |
692 | 713 | : 'auto'
|
693 | 714 | };
|
694 | 715 | height: ${$rowHeights && $rowHeights[+row.id] ? `${$rowHeights[+row.id].min}px` : 'auto'};
|
|
698 | 719 | <div
|
699 | 720 | class="flex items-start overflow-auto"
|
700 | 721 | style={`
|
701 |
| - max-height: ${$rowHeights && $rowHeights[row.id] ? `${$rowHeights[row.id].max}px` : 'auto'}; |
| 722 | + max-height: ${$rowHeights && $rowHeights[+row.id] ? `${$rowHeights[+row.id].max}px` : 'auto'}; |
702 | 723 | `}
|
703 | 724 | >
|
704 | 725 | <div
|
|
0 commit comments