Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,7 @@
class="si-calendar-cell"
[attr.data-row]="rowIndex"
[attr.data-col]="colIndex"
[class.range-hover]="
previewRange() && selection().previewRangeHover(col, activeHover(), startDate())
"
[class.range-hover-end]="
previewRange() && selection().previewRangeHoverEnd(col, activeHover(), startDate())
"
[class.range]="selection().inRange(col, startDate(), endDate())"
[class.range-start]="selection().isRangeSelected(col, startDate())"
[class.range-end]="selection().isRangeSelected(col, endDate())"
[class]="cellRangeClasses()[rowIndex][colIndex]"
>
<button
siCalendarDateCell
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,37 @@ export class SiCalendarBodyComponent {
: new SingleSelectionStrategy(this.compareAdapter())
);

protected readonly cellRangeClasses = computed(() => {
const rows = this.rows();
const previewRange = this.previewRange();
const sel = this.selection();
const hover = this.activeHover();
const start = this.startDate();
const end = this.endDate();

return rows.map(row =>
row.map(col => {
const classes: string[] = [];
if (previewRange && sel.previewRangeHover(col, hover, start)) {
classes.push('range-hover');
}
if (previewRange && sel.previewRangeHoverEnd(col, hover, start)) {
classes.push('range-hover-end');
}
if (sel.inRange(col, start, end)) {
classes.push('range');
}
if (sel.isRangeSelected(col, start)) {
classes.push('range-start');
}
if (sel.isRangeSelected(col, end)) {
classes.push('range-end');
}
return classes.join(' ');
})
);
});
Comment on lines +204 to +233
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The cellRangeClasses computed signal currently depends on activeHover() unconditionally. This means the entire grid's classes will be re-calculated on every mouse move, even when range selection is disabled or the preview is turned off.

To optimize performance, especially in single selection mode, you should only read the activeHover() signal when it's actually needed for the range preview logic. This prevents the computed signal from registering a dependency on activeHover when it wouldn't affect the output.

  protected readonly cellRangeClasses = computed(() => {
    const rows = this.rows();
    const sel = this.selection();
    const previewRange = this.previewRange();
    const start = this.startDate();
    const end = this.endDate();

    // Only track hover if it's actually needed for the preview logic.
    // This prevents unnecessary re-computations during mouse movement 
    // when range selection or preview is disabled.
    const hover = (previewRange && sel instanceof RangeSelectionStrategy) 
      ? this.activeHover() 
      : undefined;

    return rows.map(row =>
      row.map(col => {
        const classes: string[] = [];
        if (hover) {
          if (sel.previewRangeHover(col, hover, start)) {
            classes.push('range-hover');
          }
          if (sel.previewRangeHoverEnd(col, hover, start)) {
            classes.push('range-hover-end');
          }
        }
        if (sel.inRange(col, start, end)) {
          classes.push('range');
        }
        if (sel.isRangeSelected(col, start)) {
          classes.push('range-start');
        }
        if (sel.isRangeSelected(col, end)) {
          classes.push('range-end');
        }
        return classes.join(' ');
      })
    );
  });


/**
* Focus calendar cell which is marked as active cell.
*/
Expand Down
Loading