virtua 0.52.0 → 0.52.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -405,14 +405,30 @@ var createListLayout = (length, itemSize, snapshot) => {
405
405
  var getAxisLength = (axis) => typeof axis === "number" ? axis : axis.length;
406
406
  var getAxisItem = (axis, index) => typeof axis === "number" ? index : axis[index];
407
407
  var createGridLayout = (axis, size, gap = 0) => {
408
+ let header = 0;
409
+ let footer = 0;
410
+ const setPinned = (nextHeader = 0, nextFooter = 0) => {
411
+ header = nextHeader;
412
+ footer = nextFooter;
413
+ };
414
+ const getPinnedStart = (length) => min(header, length);
415
+ const getTrailStart = (length) => max(length - footer, getPinnedStart(length));
416
+ const pinRange = (getRange, getOffset, length, startOffset, endOffset) => {
417
+ const insetStart = getOffset(getPinnedStart(length));
418
+ const insetEnd = getOffset(length) - getOffset(getTrailStart(length));
419
+ const start = startOffset + (insetStart ? insetStart - gap : 0);
420
+ return getRange(start, max(start, endOffset - (insetEnd ? insetEnd - gap : 0)));
421
+ };
408
422
  if (typeof size === "number") {
409
423
  let length = getAxisLength(axis);
410
424
  let itemSize = size;
411
425
  const findIndex = (offset) => itemSize + gap ? clamp(floor(offset / (itemSize + gap)), 0, length - 1) : 0;
426
+ const getItemOffset = (index) => index * (itemSize + gap);
427
+ const findRange = (startOffset, endOffset) => [findIndex(startOffset), findIndex(endOffset)];
412
428
  return {
413
- $getRange: (startOffset, endOffset) => [findIndex(startOffset), findIndex(endOffset)],
429
+ $getRange: (startOffset, endOffset) => pinRange(findRange, getItemOffset, length, startOffset, endOffset),
414
430
  $findIndex: findIndex,
415
- $getItemOffset: (index) => index * (itemSize + gap),
431
+ $getItemOffset: getItemOffset,
416
432
  $getItemSize: () => itemSize,
417
433
  $setItemSize: () => false,
418
434
  $isSizeEqual: () => false,
@@ -423,6 +439,9 @@ var createGridLayout = (axis, size, gap = 0) => {
423
439
  return 0;
424
440
  },
425
441
  $isMeasurable: () => false,
442
+ $setPinned: setPinned,
443
+ $getPinnedStart: () => getPinnedStart(length),
444
+ $getTrailStart: () => getTrailStart(length),
426
445
  $setAxis: (_axis, nextSize, scrollOffset) => {
427
446
  if (typeof nextSize !== "number" || nextSize === itemSize) {
428
447
  return;
@@ -441,7 +460,7 @@ var createGridLayout = (axis, size, gap = 0) => {
441
460
  const inner = createListLayout(length, undefined, [[], 40 + gap]);
442
461
  const isMeasurable = (index) => isAuto || !!autos[index];
443
462
  const layout = {
444
- $getRange: inner.$getRange,
463
+ $getRange: (startOffset, endOffset) => pinRange(inner.$getRange, inner.$getItemOffset, inner.$getLength(), startOffset, endOffset),
445
464
  $findIndex: inner.$findIndex,
446
465
  $getItemOffset: inner.$getItemOffset,
447
466
  $getItemSize: (index) => inner.$getItemSize(index) - gap,
@@ -452,6 +471,9 @@ var createGridLayout = (axis, size, gap = 0) => {
452
471
  $setLength: inner.$setLength,
453
472
  $estimateDefaultSize: isAuto ? inner.$estimateDefaultSize : undefined,
454
473
  $isMeasurable: isMeasurable,
474
+ $setPinned: setPinned,
475
+ $getPinnedStart: () => getPinnedStart(inner.$getLength()),
476
+ $getTrailStart: () => getTrailStart(inner.$getLength()),
455
477
  $setAxis: (nextAxis, requestedSize, scrollOffset, mutable) => {
456
478
  if (isAuto) {
457
479
  return;
@@ -492,8 +514,9 @@ var createGridLayout = (axis, size, gap = 0) => {
492
514
 
493
515
  //#endregion
494
516
  //#region src/core/grid.ts
495
- var updateGridAxis = (store, layout, axis, size, mutable) => {
517
+ var updateGridAxis = (store, layout, axis, size, header, footer, mutable) => {
496
518
  const length = getAxisLength(axis);
519
+ layout.$setPinned(header, footer);
497
520
  if (length !== store.$getItemsLength()) {
498
521
  store.$update(5, [length]);
499
522
  }
@@ -523,7 +546,7 @@ var getSectionStarts = (sectionRows, pinnedStart, trailStart) => {
523
546
  }
524
547
  return sort(starts);
525
548
  };
526
- var getSection = (starts, rowIndex, trailStart) => {
549
+ var getSectionIndex = (starts, rowIndex, trailStart) => {
527
550
  if (rowIndex >= trailStart) {
528
551
  return -1;
529
552
  }
@@ -540,37 +563,32 @@ var getSection = (starts, rowIndex, trailStart) => {
540
563
  return lo - 1;
541
564
  };
542
565
  var addSectionHeader = (extras, sectionStarts, rowIndex, trailStart) => {
543
- const section = getSection(sectionStarts, rowIndex, trailStart);
566
+ const section = getSectionIndex(sectionStarts, rowIndex, trailStart);
544
567
  if (section >= 0) {
545
568
  extras.push(sectionStarts[section]);
546
569
  }
547
570
  };
548
- var getTrackIndexes = (extras, count, pinnedStart, start, end, trailStart) => {
549
- const indexes = [];
550
- for (let i = 0; i < pinnedStart; i++) {
551
- indexes.push(i);
552
- }
571
+ var addExtras = (indexes, extras, e, bound, lastRendered) => {
553
572
  const extrasLength = extras.length;
554
- let e = 0;
555
- let last = pinnedStart - 1;
556
- for (; e < extrasLength && extras[e] < start; e++) {
573
+ for (; e < extrasLength && extras[e] < bound; e++) {
557
574
  const i = extras[e];
558
- if (i > last) {
575
+ if (i > lastRendered) {
559
576
  indexes.push(i);
560
- last = i;
577
+ lastRendered = i;
561
578
  }
562
579
  }
563
- for (let i = start; i <= end; i++) {
580
+ return e;
581
+ };
582
+ var getTrackIndexes = (extras, count, pinnedStart, start, end, trailStart) => {
583
+ const indexes = [];
584
+ for (let i = 0; i < pinnedStart; i++) {
564
585
  indexes.push(i);
565
586
  }
566
- last = end;
567
- for (; e < extrasLength && extras[e] < trailStart; e++) {
568
- const i = extras[e];
569
- if (i > last) {
570
- indexes.push(i);
571
- last = i;
572
- }
587
+ const e = addExtras(indexes, extras, 0, start, pinnedStart - 1);
588
+ for (let i = start; i <= end; i++) {
589
+ indexes.push(i);
573
590
  }
591
+ addExtras(indexes, extras, e, trailStart, end);
574
592
  for (let i = trailStart; i < count; i++) {
575
593
  indexes.push(i);
576
594
  }
@@ -585,29 +603,24 @@ var getTemplate = (layout, indexes, measured, sortedCuts, measuredSize, count) =
585
603
  let line = 0;
586
604
  let i = 0;
587
605
  let c = 0;
588
- while (i < indexesLength || c < cutsLength) {
589
- const index = i < indexesLength ? indexes[i] : count;
590
- const cut = c < cutsLength ? sortedCuts[c] : count;
591
- if (cut <= line) {
606
+ while (line < count) {
607
+ while (c < cutsLength && sortedCuts[c] <= line) {
592
608
  c++;
609
+ }
610
+ const index = i < indexesLength ? indexes[i] : count;
611
+ let to;
612
+ let size;
613
+ if (index === line) {
614
+ to = line + 1;
615
+ const m = measured[i];
616
+ size = m == null ? layout.$getItemSize(line) + "px" : m ? measuredSize : "minmax(" + layout.$getItemSize(line) + "px,auto)";
617
+ i++;
593
618
  } else {
594
- let to;
595
- let size;
596
- if (index === line) {
597
- to = line + 1;
598
- const m = measured[i];
599
- size = m == null ? layout.$getItemSize(line) + "px" : m ? measuredSize : "minmax(" + layout.$getItemSize(line) + "px,auto)";
600
- i++;
601
- } else {
602
- to = min(index, cut);
603
- size = "minmax(" + (layout.$getItemOffset(to - 1) + layout.$getItemSize(to - 1) - layout.$getItemOffset(line)) + "px,auto)";
604
- }
605
- template += " " + size + " [l" + to + "]";
606
- line = to;
619
+ to = min(index, c < cutsLength ? sortedCuts[c] : count);
620
+ size = "minmax(" + (layout.$getItemOffset(to - 1) + layout.$getItemSize(to - 1) - layout.$getItemOffset(line)) + "px,auto)";
607
621
  }
608
- }
609
- if (line < count) {
610
- template += " minmax(" + (layout.$getTotalSize() - layout.$getItemOffset(line)) + "px,auto) [l" + count + "]";
622
+ template += " " + size + " [l" + to + "]";
623
+ line = to;
611
624
  }
612
625
  return template;
613
626
  };
@@ -618,13 +631,13 @@ var gridStyleToString = (style) => {
618
631
  }
619
632
  return css;
620
633
  };
621
- var createGridPlan = (rowLayout, colLayout, rowRange, colRange, headerRows = 0, sectionRows = EMPTY, footerRows = 0, headerCols = 0, footerCols = 0, spans = EMPTY, kept = EMPTY, sortedCell) => {
622
- const rowCount = rowLayout.$getLength();
623
- const colCount = colLayout.$getLength();
624
- const rowPinnedStart = min(headerRows, rowCount);
625
- const rowTrailStart = max(rowCount - footerRows, rowPinnedStart);
626
- const colPinnedStart = min(headerCols, colCount);
627
- const colTrailStart = max(colCount - footerCols, colPinnedStart);
634
+ var createGridPlan = (rowLayout, colLayout, rowRange, colRange, sectionRows = EMPTY, spans = EMPTY, kept = EMPTY, sortedCell) => {
635
+ const totalRowCount = rowLayout.$getLength();
636
+ const totalColCount = colLayout.$getLength();
637
+ const rowPinnedStart = rowLayout.$getPinnedStart();
638
+ const rowTrailStart = rowLayout.$getTrailStart();
639
+ const colPinnedStart = colLayout.$getPinnedStart();
640
+ const colTrailStart = colLayout.$getTrailStart();
628
641
  const rowRangeStart = clamp(rowRange[0], rowPinnedStart, rowTrailStart);
629
642
  const rowRangeEnd = min(rowRange[1], rowTrailStart - 1);
630
643
  const colRangeStart = clamp(colRange[0], colPinnedStart, colTrailStart);
@@ -635,7 +648,7 @@ var createGridPlan = (rowLayout, colLayout, rowRange, colRange, headerRows = 0,
635
648
  const extraCols = [];
636
649
  const extraCells = [];
637
650
  for (const cell of kept) {
638
- if (cell.rowIndex < rowCount && cell.colIndex < colCount) {
651
+ if (cell.rowIndex < totalRowCount && cell.colIndex < totalColCount) {
639
652
  extraCells.push(cell);
640
653
  }
641
654
  }
@@ -657,17 +670,16 @@ var createGridPlan = (rowLayout, colLayout, rowRange, colRange, headerRows = 0,
657
670
  for (const span of waiting) {
658
671
  const row = span.rowIndex;
659
672
  const col = span.colIndex;
660
- const rowTo = getSpanRowEnd(span, rowCount);
661
- const colTo = getSpanColEnd(span, colCount);
662
- if (row < rowCount && col < colCount && (rowTo - row > 1 || colTo - col > 1)) {
663
- if (hasTrackIn(extraRows, row, rowTo, rowPinnedStart, rowRangeStart, rowRangeEnd, rowTrailStart)) {
664
- if (hasTrackIn(extraCols, col, colTo, colPinnedStart, colRangeStart, colRangeEnd, colTrailStart)) {
665
- extraCells.push(span);
666
- } else {
667
- const section = getSection(sectionStarts, rowTo - 1, rowTrailStart);
668
- if (row < rowPinnedStart || section >= 0 && sectionStarts[section] >= row) {
669
- rest.push(span);
670
- }
673
+ const rowTo = getSpanRowEnd(span, totalRowCount);
674
+ const colTo = getSpanColEnd(span, totalColCount);
675
+ if (row < totalRowCount && col < totalColCount && (rowTo - row > 1 || colTo - col > 1)) {
676
+ const hasRenderedRow = hasTrackIn(extraRows, row, rowTo, rowPinnedStart, rowRangeStart, rowRangeEnd, rowTrailStart);
677
+ if (hasRenderedRow && hasTrackIn(extraCols, col, colTo, colPinnedStart, colRangeStart, colRangeEnd, colTrailStart)) {
678
+ extraCells.push(span);
679
+ } else if (hasRenderedRow) {
680
+ const section = getSectionIndex(sectionStarts, rowTo - 1, rowTrailStart);
681
+ if (row < rowPinnedStart || section >= 0 && sectionStarts[section] >= row) {
682
+ rest.push(span);
671
683
  }
672
684
  } else if (col < colPinnedStart) {
673
685
  rest.push(span);
@@ -678,22 +690,22 @@ var createGridPlan = (rowLayout, colLayout, rowRange, colRange, headerRows = 0,
678
690
  } while (l < extraCells.length);
679
691
  sort(extraRows);
680
692
  sort(extraCols);
681
- const rowIndexes = getTrackIndexes(extraRows, rowCount, rowPinnedStart, rowRangeStart, rowRangeEnd, rowTrailStart);
682
- const cols = getTrackIndexes(extraCols, colCount, colPinnedStart, colRangeStart, colRangeEnd, colTrailStart);
683
- const rowLength = rowIndexes.length;
684
- const colLength = cols.length;
693
+ const rows = getTrackIndexes(extraRows, totalRowCount, rowPinnedStart, rowRangeStart, rowRangeEnd, rowTrailStart);
694
+ const cols = getTrackIndexes(extraCols, totalColCount, colPinnedStart, colRangeStart, colRangeEnd, colTrailStart);
695
+ const rowsLength = rows.length;
696
+ const colsLength = cols.length;
685
697
  const spanCells = new Map();
686
698
  const rowCuts = [];
687
699
  const colCuts = [];
688
700
  for (const span of extraCells) {
689
- const rowTo = getSpanRowEnd(span, rowCount);
690
- const colTo = getSpanColEnd(span, colCount);
701
+ const rowTo = getSpanRowEnd(span, totalRowCount);
702
+ const colTo = getSpanColEnd(span, totalColCount);
691
703
  rowCuts.push(rowTo);
692
704
  colCuts.push(colTo);
693
705
  const colStart = cols.indexOf(span.colIndex);
694
- for (let i = rowIndexes.indexOf(span.rowIndex); i < rowLength && rowIndexes[i] < rowTo; i++) {
695
- const rowKey = rowIndexes[i] * colCount;
696
- for (let j = colStart; j < colLength && cols[j] < colTo; j++) {
706
+ for (let i = rows.indexOf(span.rowIndex); i < rowsLength && rows[i] < rowTo; i++) {
707
+ const rowKey = rows[i] * totalColCount;
708
+ for (let j = colStart; j < colsLength && cols[j] < colTo; j++) {
697
709
  spanCells.set(rowKey + cols[j], span);
698
710
  }
699
711
  }
@@ -703,137 +715,138 @@ var createGridPlan = (rowLayout, colLayout, rowRange, colRange, headerRows = 0,
703
715
  measuredCols.push(colLayout.$isMeasurable(colIndex) ? false : null);
704
716
  }
705
717
  const measuredRows = [];
706
- const stickyTop = rowLayout.$getItemOffset(rowPinnedStart);
718
+ const sectionHeaderTop = rowLayout.$getItemOffset(rowPinnedStart);
707
719
  const groups = [];
708
720
  let groupRows = groups;
709
721
  const prev = rowStatesCache.get(rowLayout);
710
722
  const rowStates = new Map();
711
- for (const rowIndex of rowIndexes) {
712
- const pinnedTop = rowIndex < rowPinnedStart;
713
- const pinnedBottom = rowIndex >= rowTrailStart;
714
- const rowInRangeOrPinnedToEnd = pinnedBottom || rowIndex >= rowRangeStart && rowIndex <= rowRangeEnd;
715
- const section = getSection(sectionStarts, rowIndex, rowTrailStart);
716
- const groupStart = pinnedTop ? 0 : pinnedBottom ? rowTrailStart : section < 0 ? -1 : sectionStarts[section];
723
+ for (const rowIndex of rows) {
724
+ const isRowPinnedStart = rowIndex < rowPinnedStart;
725
+ const isRowPinnedEnd = rowIndex >= rowTrailStart;
726
+ const isRowInRangeOrPinnedToEnd = isRowPinnedEnd || rowIndex >= rowRangeStart && rowIndex <= rowRangeEnd;
727
+ const section = getSectionIndex(sectionStarts, rowIndex, rowTrailStart);
728
+ const groupStart = isRowPinnedStart ? 0 : isRowPinnedEnd ? rowTrailStart : section < 0 ? -1 : sectionStarts[section];
717
729
  if (rowIndex === groupStart) {
718
- const groupEnd = pinnedTop ? rowPinnedStart : pinnedBottom ? rowCount : section + 1 < sectionLength ? sectionStarts[section + 1] : rowTrailStart;
730
+ const groupEnd = isRowPinnedStart ? rowPinnedStart : isRowPinnedEnd ? totalRowCount : section + 1 < sectionLength ? sectionStarts[section + 1] : rowTrailStart;
719
731
  rowCuts.push(groupEnd);
720
- const rows = [];
732
+ const groupedRows = [];
721
733
  groups.push({
722
- $key: pinnedTop ? -1 : pinnedBottom ? -2 : -3 - groupStart,
723
- $rows: rows,
724
- $style: getBoxStyle(groupStart, groupEnd, pinnedTop || pinnedBottom ? 0 : null, pinnedBottom ? "bottom" : "top", 4)
734
+ $key: isRowPinnedStart ? -1 : isRowPinnedEnd ? -2 : -3 - groupStart,
735
+ $rows: groupedRows,
736
+ $style: getBoxStyle(groupStart, groupEnd, isRowPinnedStart || isRowPinnedEnd ? 0 : null, isRowPinnedEnd ? "bottom" : "top", 4)
725
737
  });
726
- groupRows = rows;
738
+ groupRows = groupedRows;
727
739
  } else if (groupStart < 0) {
728
740
  groupRows = groups;
729
741
  }
730
742
  const isSectionHeaderRow = section >= 0 && rowIndex === groupStart;
731
- const rowTop = isSectionHeaderRow ? stickyTop : null;
732
- const rowKey = rowIndex * colCount;
743
+ const rowTop = isSectionHeaderRow ? sectionHeaderTop : null;
744
+ const rowKey = rowIndex * totalColCount;
733
745
  const prevRow = prev && prev.get(rowIndex);
734
746
  const prevCells = prevRow && prevRow.$cells;
735
747
  const rowCells = [];
736
748
  let p = 0;
737
749
  let measuredRow = rowLayout.$isMeasurable(rowIndex) ? false : null;
738
750
  let rowEnd = rowIndex + 1;
739
- let changed = false;
740
- for (let i = 0; i < colLength; i++) {
751
+ let hasChanged = false;
752
+ for (let i = 0; i < colsLength; i++) {
741
753
  const colIndex = cols[i];
742
- const startPinned = colIndex < colPinnedStart;
743
- const endPinned = colIndex >= colTrailStart;
744
- const colInRangeOrPinnedToEnd = endPinned || colIndex >= colRangeStart && colIndex <= colRangeEnd;
754
+ const isColPinnedStart = colIndex < colPinnedStart;
755
+ const isColPinnedEnd = colIndex >= colTrailStart;
756
+ const isColInRangeOrPinnedToEnd = isColPinnedEnd || colIndex >= colRangeStart && colIndex <= colRangeEnd;
745
757
  const span = spanCells.get(rowKey + colIndex);
746
- if (span ? span.rowIndex !== rowIndex || span.colIndex !== colIndex : !(rowInRangeOrPinnedToEnd && colInRangeOrPinnedToEnd) && !pinnedTop && !isSectionHeaderRow && !startPinned) {
747
- continue;
748
- }
749
- const rowTo = span ? getSpanRowEnd(span, rowCount) : rowIndex + 1;
750
- const colTo = span ? getSpanColEnd(span, colCount) : colIndex + 1;
751
- const spansRows = rowTo - rowIndex > 1;
752
- const spansCols = colTo - colIndex > 1;
753
- const spanning = spansRows || spansCols;
754
- const rowSpan = spanning ? rowTo - rowIndex : undefined;
755
- const colSpan = spanning ? colTo - colIndex : undefined;
756
- let measureRowIndex;
757
- let measureColIndex;
758
- rowEnd = max(rowEnd, rowTo);
759
- const stickyStart = startPinned ? colLayout.$getItemOffset(colIndex) : null;
760
- const stickyEnd = endPinned ? colLayout.$getTotalSize() - colLayout.$getItemOffset(colTo - 1) - colLayout.$getItemSize(colTo - 1) : null;
761
- if (measuredRow === false && !spansRows) {
762
- measureRowIndex = rowIndex;
763
- measuredRow = true;
764
- }
765
- if (measuredCols[i] === false && !spansCols) {
766
- measureColIndex = colIndex;
767
- measuredCols[i] = true;
768
- }
769
- const role = pinnedTop ? "columnheader" : colIndex === rowHeaderCol && (startPinned || isSectionHeaderRow) ? "rowheader" : "cell";
770
- const sortOrder = role !== "cell" && sortedCell && sortedCell.rowIndex === rowIndex && sortedCell.colIndex === colIndex ? sortedCell.order : undefined;
771
- let cell;
772
- if (prevCells) {
773
- while (p < prevCells.length && prevCells[p].$col < colIndex) {
774
- p++;
758
+ if (span ? span.rowIndex === rowIndex && span.colIndex === colIndex : isRowInRangeOrPinnedToEnd && isColInRangeOrPinnedToEnd || isRowPinnedStart || isSectionHeaderRow || isColPinnedStart) {
759
+ const rowTo = span ? getSpanRowEnd(span, totalRowCount) : rowIndex + 1;
760
+ const colTo = span ? getSpanColEnd(span, totalColCount) : colIndex + 1;
761
+ const rowSpan = rowTo - rowIndex;
762
+ const colSpan = colTo - colIndex;
763
+ const isSpanningRows = rowSpan > 1;
764
+ const isSpanningCols = colSpan > 1;
765
+ const isSpanning = isSpanningRows || isSpanningCols;
766
+ let measureRowIndex;
767
+ let measureColIndex;
768
+ rowEnd = max(rowEnd, rowTo);
769
+ const stickyStart = isColPinnedStart ? colLayout.$getItemOffset(colIndex) : null;
770
+ const stickyEnd = isColPinnedEnd ? colLayout.$getTotalSize() - colLayout.$getItemOffset(colTo - 1) - colLayout.$getItemSize(colTo - 1) : null;
771
+ if (measuredRow === false && !isSpanningRows) {
772
+ measureRowIndex = rowIndex;
773
+ measuredRow = true;
775
774
  }
776
- if (p < prevCells.length) {
777
- cell = prevCells[p];
778
- }
779
- }
780
- if (!cell || cell.$col !== colIndex || cell.$rowSpan !== rowSpan || cell.$colSpan !== colSpan || cell.$start !== stickyStart || cell.$end !== stickyEnd || cell.$measureRow !== measureRowIndex || cell.$measureCol !== measureColIndex || cell.$role !== role || cell.$sort !== sortOrder) {
781
- const style = {
782
- contain: "layout style",
783
- display: "grid",
784
- gridArea: spanning ? "1/l" + colIndex + "/l" + rowTo + "/l" + colTo : "1/l" + colIndex
785
- };
786
- if (spansRows) {
787
- style["height"] = "0px";
788
- style["minHeight"] = "100%";
789
- style["zIndex"] = 1;
775
+ if (measuredCols[i] === false && !isSpanningCols) {
776
+ measureColIndex = colIndex;
777
+ measuredCols[i] = true;
790
778
  }
791
- if (spansCols) {
792
- style["width"] = "0px";
793
- style["minWidth"] = "100%";
779
+ const role = isRowPinnedStart ? "columnheader" : colIndex === rowHeaderCol && (isColPinnedStart || isSectionHeaderRow) ? "rowheader" : "cell";
780
+ const ariaRowSpan = isSpanning ? rowSpan : undefined;
781
+ const ariaColSpan = isSpanning ? colSpan : undefined;
782
+ const ariaSort = role !== "cell" && sortedCell && sortedCell.rowIndex === rowIndex && sortedCell.colIndex === colIndex ? sortedCell.order : undefined;
783
+ let cell;
784
+ if (prevCells) {
785
+ const prevCellsLength = prevCells.length;
786
+ while (p < prevCellsLength && prevCells[p].$col < colIndex) {
787
+ p++;
788
+ }
789
+ if (p < prevCellsLength && prevCells[p].$col === colIndex) {
790
+ cell = prevCells[p];
791
+ }
794
792
  }
795
- if (startPinned || endPinned) {
796
- if (startPinned) {
797
- style["insetInlineStart"] = stickyStart + "px";
798
- } else {
799
- style["insetInlineEnd"] = stickyEnd + "px";
793
+ if (!cell || cell.$rowSpan !== ariaRowSpan || cell.$colSpan !== ariaColSpan || cell.$start !== stickyStart || cell.$end !== stickyEnd || cell.$measureRow !== measureRowIndex || cell.$measureCol !== measureColIndex || cell.$role !== role || cell.$sort !== ariaSort) {
794
+ let gridArea = "1/l" + colIndex;
795
+ if (isSpanning) {
796
+ gridArea += "/l" + rowTo + "/l" + colTo;
797
+ }
798
+ const style = {
799
+ contain: "layout style",
800
+ display: "grid",
801
+ gridArea
802
+ };
803
+ if (isSpanningRows) {
804
+ style["height"] = "0px";
805
+ style["minHeight"] = "100%";
806
+ style["zIndex"] = 1;
807
+ }
808
+ if (isSpanningCols) {
809
+ style["width"] = "0px";
810
+ style["minWidth"] = "100%";
800
811
  }
801
- style["position"] = "sticky";
802
- style["zIndex"] = 2;
812
+ if (isColPinnedStart || isColPinnedEnd) {
813
+ style[isColPinnedStart ? "insetInlineStart" : "insetInlineEnd"] = (isColPinnedStart ? stickyStart : stickyEnd) + "px";
814
+ style["position"] = "sticky";
815
+ style["zIndex"] = 2;
816
+ }
817
+ cell = {
818
+ $col: colIndex,
819
+ $rowSpan: ariaRowSpan,
820
+ $colSpan: ariaColSpan,
821
+ $measureRow: measureRowIndex,
822
+ $measureCol: measureColIndex,
823
+ $role: role,
824
+ $sort: ariaSort,
825
+ $style: style,
826
+ $start: stickyStart,
827
+ $end: stickyEnd
828
+ };
829
+ hasChanged = true;
803
830
  }
804
- cell = {
805
- $col: colIndex,
806
- $rowSpan: rowSpan,
807
- $colSpan: colSpan,
808
- $measureRow: measureRowIndex,
809
- $measureCol: measureColIndex,
810
- $role: role,
811
- $sort: sortOrder,
812
- $style: style,
813
- $start: stickyStart,
814
- $end: stickyEnd
815
- };
816
- changed = true;
831
+ rowCells.push(cell);
817
832
  }
818
- rowCells.push(cell);
819
833
  }
820
834
  measuredRows.push(measuredRow);
821
- if (!rowCells.length) {
822
- continue;
835
+ if (rowCells.length) {
836
+ const row = prevRow && !hasChanged && prevRow.$cells.length === rowCells.length && prevRow.$top === rowTop ? prevRow : {
837
+ $row: rowIndex,
838
+ $cells: rowCells,
839
+ $style: getBoxStyle(rowIndex, rowEnd, rowTop, "top", 3),
840
+ $top: rowTop
841
+ };
842
+ rowStates.set(rowIndex, row);
843
+ groupRows.push(row);
823
844
  }
824
- const row = prevRow && !changed && prevRow.$cells.length === rowCells.length && prevRow.$top === rowTop ? prevRow : {
825
- $row: rowIndex,
826
- $cells: rowCells,
827
- $style: getBoxStyle(rowIndex, rowEnd, rowTop, "top", 3),
828
- $top: rowTop
829
- };
830
- rowStates.set(rowIndex, row);
831
- groupRows.push(row);
832
845
  }
833
846
  rowStatesCache.set(rowLayout, rowStates);
834
847
  return {
835
- $rowTemplate: getTemplate(rowLayout, rowIndexes, measuredRows, sort(rowCuts), "max-content", rowCount),
836
- $colTemplate: getTemplate(colLayout, cols, measuredCols, sort(colCuts), "minmax(max-content,auto)", colCount),
848
+ $rowTemplate: getTemplate(rowLayout, rows, measuredRows, sort(rowCuts), "max-content", totalRowCount),
849
+ $colTemplate: getTemplate(colLayout, cols, measuredCols, sort(colCuts), "minmax(max-content,auto)", totalColCount),
837
850
  $groups: groups
838
851
  };
839
852
  };
@@ -1298,47 +1311,49 @@ var gridScrollBy = (driver, rowStore, colStore, vertical, horizontal) => {
1298
1311
  driver.$scroll(true, () => offset);
1299
1312
  }
1300
1313
  };
1301
- var scrollGridAxisToIndex = (driver, store, header, sections, footer, index, align, isHorizontal) => {
1314
+ var scrollGridAxisToIndex = (driver, store, layout, sections, index, align, isHorizontal) => {
1302
1315
  const count = store.$getItemsLength();
1303
- const pinnedStart = min(header, count);
1304
- const trailStart = max(count - footer, pinnedStart);
1316
+ const pinnedStart = layout.$getPinnedStart();
1317
+ const trailStart = layout.$getTrailStart();
1305
1318
  index = clamp(index, 0, count - 1);
1306
1319
  const starts = getSectionStarts(sections, pinnedStart, trailStart);
1307
- const section = getSection(starts, index, trailStart);
1320
+ const section = getSectionIndex(starts, index, trailStart);
1308
1321
  const sectionHeader = section < 0 ? -1 : starts[section];
1309
- const getInsets = () => [store.$getItemOffset(pinnedStart) - store.$getItemOffset(0) + (sectionHeader < 0 || sectionHeader === index ? 0 : store.$getItemOffset(sectionHeader + 1) - store.$getItemOffset(sectionHeader)), store.$getItemOffset(count) - store.$getItemOffset(trailStart)];
1322
+ const getInsetStart = () => layout.$getItemOffset(pinnedStart) + (sectionHeader < 0 || sectionHeader === index ? 0 : store.$getItemOffset(sectionHeader + 1) - store.$getItemOffset(sectionHeader));
1323
+ const getInsetEnd = () => layout.$getItemOffset(count) - layout.$getItemOffset(trailStart);
1310
1324
  if (align === "nearest") {
1311
1325
  if (index < pinnedStart || index >= trailStart) {
1312
1326
  return;
1313
1327
  }
1314
- const [insetStart, insetEnd] = getInsets();
1315
- const scrollOffset = store.$getScrollOffset();
1328
+ const insetStart = getInsetStart();
1329
+ const scrollOffset = store.$getScrollOffset() + insetStart;
1330
+ const viewportSize = store.$getViewportSize() - insetStart - getInsetEnd();
1316
1331
  const itemSize = store.$getItemSize(index);
1317
1332
  let itemOffset = store.$getItemOffset(index);
1318
1333
  if (sectionHeader === index) {
1319
1334
  const lastIndex = (section + 1 < starts.length ? starts[section + 1] : trailStart) - 1;
1320
- itemOffset = max(itemOffset, min(scrollOffset + insetStart, store.$getItemOffset(lastIndex) + store.$getItemSize(lastIndex) - itemSize));
1335
+ itemOffset = max(itemOffset, min(scrollOffset, store.$getItemOffset(lastIndex) + store.$getItemSize(lastIndex) - itemSize));
1321
1336
  }
1322
- if (itemOffset < scrollOffset + insetStart) {
1337
+ if (itemOffset < scrollOffset) {
1323
1338
  align = "start";
1324
- } else if (itemOffset + itemSize > scrollOffset + store.$getViewportSize() - insetEnd) {
1339
+ } else if (itemOffset + itemSize > scrollOffset + viewportSize) {
1325
1340
  align = "end";
1326
1341
  } else {
1327
1342
  return;
1328
1343
  }
1329
1344
  }
1330
1345
  driver.$scroll(isHorizontal, () => {
1331
- const [insetStart, insetEnd] = getInsets();
1332
- const rest = store.$getItemSize(index) - store.$getViewportSize();
1333
- return store.$getItemOffset(index) + (align === "end" ? rest + insetEnd : align === "center" ? (rest + insetEnd - insetStart) / 2 : -insetStart);
1346
+ const insetStart = getInsetStart();
1347
+ const rest = store.$getItemSize(index) - (store.$getViewportSize() - insetStart - getInsetEnd());
1348
+ return store.$getItemOffset(index) - insetStart + (align === "end" ? rest : align === "center" ? rest / 2 : 0);
1334
1349
  });
1335
1350
  };
1336
- var gridScrollToIndex = (driver, rowStore, colStore, headerRows = 0, sectionRows = EMPTY, footerRows = 0, headerCols = 0, footerCols = 0, { rowIndex, colIndex, rowAlign, colAlign }) => {
1351
+ var gridScrollToIndex = (driver, rowStore, colStore, rowLayout, colLayout, sectionRows = EMPTY, { rowIndex, colIndex, rowAlign, colAlign }) => {
1337
1352
  if (rowIndex != null) {
1338
- scrollGridAxisToIndex(driver, rowStore, headerRows, sectionRows, footerRows, rowIndex, rowAlign, false);
1353
+ scrollGridAxisToIndex(driver, rowStore, rowLayout, sectionRows, rowIndex, rowAlign, false);
1339
1354
  }
1340
1355
  if (colIndex != null) {
1341
- scrollGridAxisToIndex(driver, colStore, headerCols, EMPTY, footerCols, colIndex, colAlign, true);
1356
+ scrollGridAxisToIndex(driver, colStore, colLayout, EMPTY, colIndex, colAlign, true);
1342
1357
  }
1343
1358
  };
1344
1359
 
@@ -1746,16 +1761,16 @@ var VGrid = (props) => {
1746
1761
  rowStore.$subscribe(8, notifyScrollEnd);
1747
1762
  colStore.$subscribe(8, notifyScrollEnd);
1748
1763
  createComputed(() => {
1749
- updateGridAxis(rowStore, rowLayout, props.rows, props.rowHeight, true);
1764
+ updateGridAxis(rowStore, rowLayout, props.rows, props.rowHeight, props.headerRows, props.footerRows, true);
1750
1765
  });
1751
1766
  createComputed(() => {
1752
- updateGridAxis(colStore, colLayout, props.cols, props.colWidth, true);
1767
+ updateGridAxis(colStore, colLayout, props.cols, props.colWidth, props.headerCols, props.footerCols, true);
1753
1768
  });
1754
1769
  const rowCount = createMemo(() => stateVersion() && rowStore.$getItemsLength());
1755
1770
  const colCount = createMemo(() => stateVersion() && colStore.$getItemsLength());
1756
1771
  const plan = createMemo(() => {
1757
1772
  stateVersion();
1758
- return createGridPlan(rowLayout, colLayout, rowStore.$getRange(props.bufferSize), colStore.$getRange(props.bufferSize), props.headerRows, props.sectionRows, props.footerRows, props.headerCols, props.footerCols, props.spans, props.keepMounted, props.ariaSort);
1773
+ return createGridPlan(rowLayout, colLayout, rowStore.$getRange(props.bufferSize), colStore.$getRange(props.bufferSize), props.sectionRows, props.spans, props.keepMounted, props.ariaSort);
1759
1774
  });
1760
1775
  const keys = createMemo(() => plan().$groups.map((state) => "$rows" in state ? state.$key : state.$row));
1761
1776
  const isScrolling = createMemo(() => stateVersion() && (rowStore.$isScrolling() || colStore.$isScrolling()));
@@ -1804,7 +1819,7 @@ var VGrid = (props) => {
1804
1819
  getColOffset: colStore.$getItemOffset,
1805
1820
  getRowSize: rowStore.$getItemSize,
1806
1821
  getColSize: colStore.$getItemSize,
1807
- scrollToIndex: (opts) => gridScrollToIndex(driver, rowStore, colStore, props.headerRows, props.sectionRows, props.footerRows, props.headerCols, props.footerCols, opts),
1822
+ scrollToIndex: (opts) => gridScrollToIndex(driver, rowStore, colStore, rowLayout, colLayout, props.sectionRows, opts),
1808
1823
  scrollTo: ({ vertical, horizontal }) => gridScrollTo(driver, vertical, horizontal),
1809
1824
  scrollBy: ({ vertical, horizontal }) => gridScrollBy(driver, rowStore, colStore, vertical, horizontal)
1810
1825
  });