// Removed duplicate import import type { SyntheticEvent } from 'react'; import type { ISettings } from './config'; import type { IMedia } from './media'; /** * DOM event wrapper for widget events * Contains the original native event from React */ export interface DOMEvent { /** The original native event from React */ originalEvent: SyntheticEvent['nativeEvent']; } /** * Event containing a post (UGC media) */ export interface PostEvent { /** The media post involved in the event */ post: IMedia; } /** * Event containing a media position (e.g., carousel index) */ export interface MediaPosition { /** Position index of the media */ position: number; } /** * Event containing a product identifier */ export interface ProductEvent { /** Product identifier involved in the event */ product: string; } /** * Carousel direction (left or right) */ export type Direction = 'left' | 'right'; /** * Arrow size for carousel navigation */ export type ArrowSize = 'nano' | 'micro' | 'small' | 'compact' | 'medium' | 'large'; /** * Carousel scroll event, triggered by arrow or native scroll */ export interface CarouselScrollEvent { /** Position index after scroll */ position: number; /** Direction of scroll */ direction: Direction; } /** * Post navigation event, triggered by arrow keys or swipe */ export interface PostNavigationEvent { /** Direction of navigation */ direction: Direction; /** The media post navigated to */ post: IMedia; } /** * Event for minimum content reached or not reached */ export interface MinContentEvent { /** Required minimum content count */ required: number; /** Current content count */ current: number; } /** * Widget layout event, describes the current layout type */ export interface LayoutEvent { /** Layout type of the widget */ layout: ISettings['type']; } /** * All widget events and their payloads */ export interface EventMap { /** * The widget has finished loading * Contains elapsed time and loaded posts */ widgetLoaded: { /** Seconds elapsed during loading */ elapsedSeconds?: number; /** List of loaded media posts */ posts: IMedia[]; } & LayoutEvent; /** * The widget has been displayed to the user * Emitted only once when the widget is visible in the viewport for at least 0.5 seconds */ widgetViewed: LayoutEvent; /** * The widget failed to load */ widgetLoadingFailed: Record; /** * A thumbnail has been loaded */ thumbnailLoaded: PostEvent & DOMEvent; /** * A thumbnail image could not be loaded */ thumbnailUnavailable: PostEvent & DOMEvent; /** * The mouse hovers a thumbnail */ thumbnailHover: PostEvent & DOMEvent; /** * A thumbnail has been viewed (at least 50% visible in the viewport) * Fires once per unique media per widget session */ thumbnailViewed: PostEvent & MediaPosition; /** * A thumbnail has been clicked */ thumbnailClicked: PostEvent & DOMEvent & MediaPosition; /** * The original post has been opened by clicking on the content */ originalPostOpened: PostEvent & DOMEvent; /** * The social profile page has been opened by clicking on the username */ socialProfileOpened: PostEvent & DOMEvent; /** * A packshot (product image) has been clicked */ packshotClicked: PostEvent & DOMEvent & ProductEvent; /** * A post has been opened (when Shop This Look is disabled) */ postOpened: PostEvent; /** * Change the viewed post by pressing left/right or clicking arrows (when Shop This Look is disabled) */ postNavigation: PostNavigationEvent; /** * An opened post has been closed (when Shop This Look is disabled) */ postClosed: PostEvent; /** * The Shop This Look (product list or modal) has been opened */ stlOpened: PostEvent; /** * Change the viewed post and Shop This Look section by pressing left/right or clicking arrows */ stlNavigation: PostNavigationEvent; /** * A product from Shop This Look has been viewed */ productViewed: PostEvent & ProductEvent; /** * A product from Shop This Look has been clicked */ productClicked: PostEvent & DOMEvent & ProductEvent; /** * The Shop This Look (product list or modal) has been closed */ stlClosed: PostEvent; /** * The mobile player has been opened */ mobilePlayerOpened: PostEvent; /** * Change the viewed post by tapping or swiping left/right in mobile player mode */ mobilePlayerNavigation: PostNavigationEvent; /** * The mobile player has been closed */ mobilePlayerClosed: PostEvent; /** * The video of the opened post is played */ videoPlayed: PostEvent & DOMEvent; /** * Scroll the carousel by using the arrows */ carouselArrowClicked: CarouselScrollEvent & DOMEvent; /** * Scroll the carousel by using the horizontal bar */ carouselNativeScroll: CarouselScrollEvent & DOMEvent; /** * Not enough content for the required min_media_to_display value */ minContentNotReached: MinContentEvent; /** * Enough content for the required min_media_to_display value */ minContentReached: MinContentEvent; } /** * Keys of all widget events */ export type EventMapKeys = keyof EventMap; /** * Callback for a widget event */ export type EventCallback = (event: T) => void; /** * List of event callbacks */ export type EventCallbacks = Array>; /** * Widget event subscription interface * Allows subscribing, unsubscribing, and triggering widget events */ export interface IWidgetEvents { /** Add a callback to listen to an event (previously added callbacks won't be overwritten) */ onEvent( eventName: EventName, callback: EventCallback, ): void; /** Remove a callback previously listening to an event */ offEvent( eventName: EventName, callback?: EventCallback, ): void; /** Trigger an event programmatically */ triggerEvent( eventName: EventName, event: EventMap[EventName], widgetId?: string, ): void; /** Check if any callback is subscribed to an event */ hasSubscribed(eventName: EventMapKeys): boolean; /** Destroy all event subscriptions for the widget */ destroy(): void; }