import React, { ComponentType, ReactNode, useEffect } from 'react'; import { StyleSheet, View, ViewStyle, ActivityIndicator, TextStyle, } from 'react-native'; import { IWidgetPayload, WidgetKind } from '@livelike/javascript'; import { useStyles, useLoadWidgetEffect, useWidgetDismiss, useAnalytics, } from '../../hooks'; import { ComponentStyleProp, LLComponentStyleFn } from '../../types'; import { LLText } from '../LLText'; export type LLCoreWidgetStyles = { widgetContainer: ViewStyle; errorText: TextStyle; }; export type LLCoreWidgetChildrenProps = { widget: IWidgetPayload; onDismiss?: () => void; }; export type LLCoreWidgetProps = ComponentStyleProp & { programId: string; widgetId: string; widgetKind: WidgetKind; LoadingComponent?: ComponentType; ErrorComponent?: ComponentType; onDismiss?: () => void; children?: (props: LLCoreWidgetChildrenProps) => ReactNode; }; export function LLCoreWidget({ programId, widgetId, widgetKind, LoadingComponent, ErrorComponent, children, onDismiss, styles: stylesProp, }: LLCoreWidgetProps) { const { dismiss, onDismissHandler } = useWidgetDismiss({ widgetId, onDismiss, }); const { isLoading, error, data } = useLoadWidgetEffect({ widgetId, widgetKind, programId, }); const styles = useStyles({ componentStylesFn: getWidgetStyles, stylesProp, }); const widget = data?.[0]; const { trackEvent } = useAnalytics(); useEffect(() => { if (!isLoading && !error && widget?.id && !dismiss) { trackEvent('Widget Displayed', { programId, widgetId: widget.id, widgetKind: widget.kind, }); } }, [isLoading, error, widget?.id, widget?.kind, dismiss, trackEvent]); if (isLoading) { return LoadingComponent ? ( ) : ( ); } if (error) { return ErrorComponent ? ( ) : ( {'Unable to load widget'} ); } if (!widget || dismiss) { return undefined; } return ( {children?.({ widget, onDismiss: onDismissHandler, })} ); } const getWidgetStyles: LLComponentStyleFn = ({ theme }) => StyleSheet.create({ widgetContainer: { display: 'flex', flexDirection: 'column', backgroundColor: theme.widgetBackground, borderRadius: 4, overflow: 'hidden', }, errorText: { display: 'flex', flex: 1, height: 100, textAlign: 'center', textAlignVertical: 'center', color: theme.error, }, });