From 21b468734c5c1f59108b8e55a9322409c60a9051 Mon Sep 17 00:00:00 2001 From: Dermot Duffy Date: Wed, 2 Oct 2024 20:28:13 -0700 Subject: [PATCH] fix: Fix thumbnail carousel scroll position (#1606) * fix: Fix thumbnail carousel scroll position * Small formatting fix --- package.json | 2 +- src/components/thumbnail-carousel.ts | 3 --- src/utils/embla/carousel-controller.ts | 5 +---- src/utils/embla/plugins/auto-size/auto-size.ts | 17 +++++++++++------ tests/utils/embla/carousel-controller.test.ts | 2 +- .../embla/plugins/auto-size/auto-size.test.ts | 7 +++++++ yarn.lock | 10 +++++----- 7 files changed, 26 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index b920af97..d732539e 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "crypto": "^1.0.1", "date-fns": "^3.6.0", "date-fns-tz": "^3.1.3", - "embla-carousel": "^8.1.4", + "embla-carousel": "^8.3.0", "embla-carousel-wheel-gestures": "^8.0.1", "home-assistant-js-websocket": "^9.4.0", "js-yaml": "^4.1.0", diff --git a/src/components/thumbnail-carousel.ts b/src/components/thumbnail-carousel.ts index 07a754c9..52361d93 100644 --- a/src/components/thumbnail-carousel.ts +++ b/src/components/thumbnail-carousel.ts @@ -15,7 +15,6 @@ import { ExtendedHomeAssistant } from '../types.js'; import { stopEventFromActivatingCardWideActions } from '../utils/action.js'; import { dispatchFrigateCardEvent } from '../utils/basic.js'; import { CarouselDirection } from '../utils/embla/carousel-controller.js'; -import AutoSize from '../utils/embla/plugins/auto-size/auto-size.js'; import { MediaQueriesResults } from '../view/media-queries-results'; import './carousel.js'; import './thumbnail.js'; @@ -43,7 +42,6 @@ export class FrigateCardThumbnailCarousel extends LitElement { public fadeThumbnails = false; protected _thumbnailSlides: TemplateResult[] = []; - protected _plugins = [AutoSize()]; protected willUpdate(changedProps: PropertyValues): void { if (changedProps.has('config')) { @@ -144,7 +142,6 @@ export class FrigateCardThumbnailCarousel extends LitElement { return html` diff --git a/src/utils/embla/carousel-controller.ts b/src/utils/embla/carousel-controller.ts index 98e36fee..076c34af 100644 --- a/src/utils/embla/carousel-controller.ts +++ b/src/utils/embla/carousel-controller.ts @@ -128,10 +128,7 @@ export class CarouselController { // This controller manages slide changes (including shadow DOM // assignments, which the stock watcher does not handle). watchSlides: false, - - // We use the auto-size plugin to manage resizes without carousel resets - // mid-scroll. - watchResize: false, + watchResize: true, watchDrag: this._draggable, }, [ diff --git a/src/utils/embla/plugins/auto-size/auto-size.ts b/src/utils/embla/plugins/auto-size/auto-size.ts index 96c41dd9..5b139837 100644 --- a/src/utils/embla/plugins/auto-size/auto-size.ts +++ b/src/utils/embla/plugins/auto-size/auto-size.ts @@ -38,9 +38,13 @@ function AutoSize(): AutoSizeType { intersectionHandler, ); - const debouncedSetContainerHeight = debounce(() => setContainerHeight(), 200, { - trailing: true, - }); + const debouncedSetContainerHeight = debounce( + () => setContainerHeightAndReInit(), + 200, + { + trailing: true, + }, + ); function init(emblaApiInstance: EmblaCarouselType): void { emblaApi = emblaApiInstance; @@ -87,8 +91,9 @@ function AutoSize(): AutoSizeType { if (isContainerIntersectingNow !== previousContainerIntersecting) { // Don't reinitialize on first call (intersectionHandler is always called - // on initial observation). - const callReInit = previousContainerIntersecting !== null; + // on initial observation), nor when the viewport is not intersecting. + const callReInit = + isContainerIntersectingNow && previousContainerIntersecting !== null; previousContainerIntersecting = isContainerIntersectingNow; if (callReInit) { reInitController?.reinit(); @@ -122,7 +127,7 @@ function AutoSize(): AutoSizeType { } } - function setContainerHeight(): void { + function setContainerHeightAndReInit(): void { const { slideRegistry, options: { axis }, diff --git a/tests/utils/embla/carousel-controller.test.ts b/tests/utils/embla/carousel-controller.test.ts index aef3fa8a..a2eb6a79 100644 --- a/tests/utils/embla/carousel-controller.test.ts +++ b/tests/utils/embla/carousel-controller.test.ts @@ -207,7 +207,7 @@ describe('CarouselController', () => { loop: true, containScroll: 'trimSnaps', watchSlides: false, - watchResize: false, + watchResize: true, watchDrag: false, }, plugins, diff --git a/tests/utils/embla/plugins/auto-size/auto-size.test.ts b/tests/utils/embla/plugins/auto-size/auto-size.test.ts index 021a01ed..26f904de 100644 --- a/tests/utils/embla/plugins/auto-size/auto-size.test.ts +++ b/tests/utils/embla/plugins/auto-size/auto-size.test.ts @@ -59,10 +59,17 @@ describe('AutoSize', () => { // First intersection handler call sets the state only. callIntersectionHandler(true); + // When not visible, will not re-init. callIntersectionHandler(false); callIntersectionHandler(false); callIntersectionHandler(false); + expect(emblaApi.reInit).not.toBeCalled(); + + // When visible, will re-initialize once. + callIntersectionHandler(true); + callIntersectionHandler(true); + expect(emblaApi.reInit).toBeCalledTimes(1); }); diff --git a/yarn.lock b/yarn.lock index 2f60368c..f408dcb4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4236,10 +4236,10 @@ __metadata: languageName: node linkType: hard -"embla-carousel@npm:^8.1.4": - version: 8.1.4 - resolution: "embla-carousel@npm:8.1.4" - checksum: 10c0/8dcd7fa5561fc354dd422440f3e24da8e2bc75617d8c053b88d44a603b69cb123a7ff3deae3eaa174b60a3a2d6bd8852b8ad21c7a3cca4692ce7da4078febf66 +"embla-carousel@npm:^8.3.0": + version: 8.3.0 + resolution: "embla-carousel@npm:8.3.0" + checksum: 10c0/0240156d6a736603d82ddfe93b03ce296e385e9c18ed2cca9465634c8adb7560bfc2fbef6368a4da2a54926c4ba6de1012ebb33d2fc92c052030ea2288e4cc92 languageName: node linkType: hard @@ -5149,7 +5149,7 @@ __metadata: date-fns: "npm:^3.6.0" date-fns-tz: "npm:^3.1.3" docsify-cli: "npm:^4.4.4" - embla-carousel: "npm:^8.1.4" + embla-carousel: "npm:^8.3.0" embla-carousel-wheel-gestures: "npm:^8.0.1" eslint: "npm:^8.57.0" eslint-config-airbnb-base: "npm:^15.0.0"