Resize the container based on media loads.
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import { EmblaCarouselType } from 'embla-carousel';
|
import { EmblaCarouselType } from 'embla-carousel';
|
||||||
import { LooseOptionsType } from 'embla-carousel/components/Options';
|
import { LooseOptionsType } from 'embla-carousel/components/Options';
|
||||||
import { CreatePluginType, LoosePluginType } from 'embla-carousel/components/Plugins';
|
import { CreatePluginType, LoosePluginType } from 'embla-carousel/components/Plugins';
|
||||||
|
import debounce from 'lodash-es/debounce';
|
||||||
import { EmblaReInitController } from '../../reinit-controller';
|
import { EmblaReInitController } from '../../reinit-controller';
|
||||||
|
|
||||||
declare module 'embla-carousel/components/Plugins' {
|
declare module 'embla-carousel/components/Plugins' {
|
||||||
@@ -37,6 +38,10 @@ function AutoSize(): AutoSizeType {
|
|||||||
intersectionHandler,
|
intersectionHandler,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const debouncedSetContainerHeight = debounce(() => setContainerHeight(), 200, {
|
||||||
|
trailing: true,
|
||||||
|
});
|
||||||
|
|
||||||
function init(emblaApiInstance: EmblaCarouselType): void {
|
function init(emblaApiInstance: EmblaCarouselType): void {
|
||||||
emblaApi = emblaApiInstance;
|
emblaApi = emblaApiInstance;
|
||||||
reInitController = new EmblaReInitController(emblaApi);
|
reInitController = new EmblaReInitController(emblaApi);
|
||||||
@@ -47,7 +52,13 @@ function AutoSize(): AutoSizeType {
|
|||||||
resizeObserver.observe(slide);
|
resizeObserver.observe(slide);
|
||||||
}
|
}
|
||||||
|
|
||||||
emblaApi.on('settle', setContainerHeight);
|
// Need to examine container size on both settle and media load, as settle
|
||||||
|
// may happen before the media is loaded (which they subsequently changes
|
||||||
|
// the size to large than the maxHeight is set).
|
||||||
|
emblaApi
|
||||||
|
.containerNode()
|
||||||
|
.addEventListener('frigate-card:media:loaded', debouncedSetContainerHeight);
|
||||||
|
emblaApi.on('settle', debouncedSetContainerHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
function destroy(): void {
|
function destroy(): void {
|
||||||
@@ -55,7 +66,10 @@ function AutoSize(): AutoSizeType {
|
|||||||
resizeObserver.disconnect();
|
resizeObserver.disconnect();
|
||||||
reInitController?.destroy();
|
reInitController?.destroy();
|
||||||
|
|
||||||
emblaApi.off('settle', setContainerHeight);
|
emblaApi
|
||||||
|
.containerNode()
|
||||||
|
.removeEventListener('frigate-card:media:loaded', debouncedSetContainerHeight);
|
||||||
|
emblaApi.off('settle', debouncedSetContainerHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
function intersectionHandler(entries: IntersectionObserverEntry[]): void {
|
function intersectionHandler(entries: IntersectionObserverEntry[]): void {
|
||||||
|
|||||||
@@ -50,9 +50,6 @@ export class EmblaReInitController {
|
|||||||
|
|
||||||
protected _debouncedReInit = debounce(
|
protected _debouncedReInit = debounce(
|
||||||
() => {
|
() => {
|
||||||
// Allow the browser a moment to paint components that are inflight, to
|
|
||||||
// ensure accurate measurements are taken during the carousel
|
|
||||||
// reinitialization.
|
|
||||||
this._scrolling = false;
|
this._scrolling = false;
|
||||||
this._shouldReInitOnScrollStop = false;
|
this._shouldReInitOnScrollStop = false;
|
||||||
this._emblaApi?.reInit();
|
this._emblaApi?.reInit();
|
||||||
|
|||||||
@@ -47,12 +47,10 @@ export class MediaGridController {
|
|||||||
protected _idAttribute: string;
|
protected _idAttribute: string;
|
||||||
|
|
||||||
protected _throttledLayout = throttle(
|
protected _throttledLayout = throttle(
|
||||||
() => {
|
() => this._masonry?.layout?.(),
|
||||||
window.requestAnimationFrame(() => this._masonry?.layout?.());
|
|
||||||
},
|
|
||||||
// Throttle layout calls to larger than the masonry.js transitionDuration
|
// Throttle layout calls to larger than the masonry.js transitionDuration
|
||||||
// value specified below.
|
// value specified below.
|
||||||
400,
|
300,
|
||||||
{ trailing: true, leading: false },
|
{ trailing: true, leading: false },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import {
|
|||||||
createTestSlideNodes,
|
createTestSlideNodes,
|
||||||
} from '../../test-utils';
|
} from '../../test-utils';
|
||||||
|
|
||||||
// Mock out debouncing (used in the reinit controller).
|
|
||||||
vi.mock('lodash-es/debounce', () => ({
|
vi.mock('lodash-es/debounce', () => ({
|
||||||
default: vi.fn((fn) => fn),
|
default: vi.fn((fn) => fn),
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import Masonry from 'masonry-layout';
|
import Masonry from 'masonry-layout';
|
||||||
import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||||
import { mock } from 'vitest-mock-extended';
|
import { mock } from 'vitest-mock-extended';
|
||||||
import { MediaLoadedInfo } from '../../src/types';
|
import { MediaLoadedInfo } from '../../src/types';
|
||||||
import {
|
import {
|
||||||
@@ -12,7 +12,6 @@ import {
|
|||||||
ResizeObserverMock,
|
ResizeObserverMock,
|
||||||
createSlot,
|
createSlot,
|
||||||
createSlotHost,
|
createSlotHost,
|
||||||
requestAnimationFrameMock,
|
|
||||||
} from '../test-utils';
|
} from '../test-utils';
|
||||||
|
|
||||||
vi.mock('lodash-es/throttle', () => ({
|
vi.mock('lodash-es/throttle', () => ({
|
||||||
@@ -82,10 +81,6 @@ describe('MediaGridController', () => {
|
|||||||
height: 20,
|
height: 20,
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeAll(() => {
|
|
||||||
window.requestAnimationFrame = requestAnimationFrameMock;
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
vi.stubGlobal('MutationObserver', MutationObserverMock);
|
vi.stubGlobal('MutationObserver', MutationObserverMock);
|
||||||
|
|||||||
Reference in New Issue
Block a user