|
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