Compare commits

..

2 Commits

Author SHA1 Message Date
Alex a5af519a05 Merge branch 'main' into fix-scroll-flicker 2026-05-27 15:44:38 -05:00
Alex Tran 0ba424dfeb test: fix scroll flicker 2026-05-27 14:50:34 -05:00
4 changed files with 23 additions and 32 deletions
@@ -206,7 +206,7 @@
<div
class={[
'group flex overflow-hidden transition-[background-color,border-radius] focus-visible:outline-none',
'group flex overflow-hidden focus-visible:outline-none',
backgroundColorClass,
{ 'rounded-xl': selected },
]}
@@ -250,12 +250,12 @@
>
<ImageThumbnail
class={[
'absolute transition-[border-radius] group-focus-visible:rounded-lg',
'absolute group-focus-visible:rounded-lg',
{ 'rounded-xl': selected },
imageClass,
]}
brokenAssetClass={[
'z-1 absolute group-focus-visible:rounded-lg transition-[border-radius]',
'z-1 absolute group-focus-visible:rounded-lg',
{ 'rounded-xl': selected },
brokenAssetClass,
]}
@@ -67,11 +67,3 @@ export function calculateViewerAssetViewportProximity(
timelineManager.visibleWindow.bottom + headerHeight,
);
}
export function calculateViewerAssetIsInOrNearViewport(
timelineManager: TimelineManager,
positionTop: number,
positionHeight: number,
) {
return isInOrNearViewport(calculateViewerAssetViewportProximity(timelineManager, positionTop, positionHeight));
}
@@ -29,8 +29,7 @@ import type { AssetDescriptor, Direction, MoveAsset, TimelineAsset } from './typ
import { ViewerAsset } from './viewer-asset.svelte';
export class TimelineMonth {
#isInOrNearViewport = $state(false);
#isInViewport = $state(false);
#viewportProximity: ViewportProximity = $state(ViewportProximity.FarFromViewport);
isLoaded: boolean = $state(false);
timelineDays: TimelineDay[] = $state([]);
readonly timelineManager: TimelineManager;
@@ -86,28 +85,24 @@ export class TimelineMonth {
}
set viewportProximity(newValue: ViewportProximity) {
const isInOrNearViewport = isInOrNearViewportUtil(newValue);
if (this.#isInOrNearViewport !== isInOrNearViewport) {
this.#isInOrNearViewport = isInOrNearViewport;
if (isInOrNearViewport) {
void this.timelineManager.loadTimelineMonth(this.yearMonth);
} else {
this.cancel();
}
const old = this.#viewportProximity;
if (old === newValue) {
return;
}
const isInViewport = isInViewportUtil(newValue);
if (this.#isInViewport !== isInViewport) {
this.#isInViewport = isInViewport;
this.#viewportProximity = newValue;
if (isInOrNearViewportUtil(newValue)) {
void this.timelineManager.loadTimelineMonth(this.yearMonth);
} else {
this.cancel();
}
}
get isInOrNearViewport() {
return this.#isInOrNearViewport;
return isInOrNearViewportUtil(this.#viewportProximity);
}
get isInViewport() {
return this.#isInViewport;
return isInViewportUtil(this.#viewportProximity);
}
get lastTimelineDay() {
@@ -1,24 +1,28 @@
import type { CommonPosition } from '$lib/utils/layout-utils';
import { calculateViewerAssetIsInOrNearViewport } from './internal/intersection-support.svelte';
import {
ViewportProximity,
calculateViewerAssetViewportProximity,
isInOrNearViewport,
} from './internal/intersection-support.svelte';
import type { TimelineDay } from './timeline-day.svelte';
import type { TimelineAsset } from './types';
export class ViewerAsset {
readonly #group: TimelineDay;
#isInOrNearViewport = $derived.by(() => {
#viewportProximity = $derived.by(() => {
if (!this.position) {
return false;
return ViewportProximity.FarFromViewport;
}
const store = this.#group.timelineMonth.timelineManager;
const positionTop = this.#group.absoluteTimelineDayTop + this.position.top;
return calculateViewerAssetIsInOrNearViewport(store, positionTop, this.position.height);
return calculateViewerAssetViewportProximity(store, positionTop, this.position.height);
});
get isInOrNearViewport() {
return this.#isInOrNearViewport;
return isInOrNearViewport(this.#viewportProximity);
}
position: CommonPosition | undefined = $state.raw();