import * as React from "react"; import { View } from "react-native"; import { useState, useRef, useEffect } from "react"; import Blocks from "../../components/blocks/blocks"; import InlinedScript from "../../components/inlined-script"; import InlinedStyles from "../../components/inlined-styles"; import { TARGET } from "../../constants/target"; import { getClassPropName } from "../../functions/get-class-prop-name"; import { isEditing } from "../../functions/is-editing"; import { isPreviewing } from "../../functions/is-previewing"; import { getDefaultCanTrack } from "../../helpers/canTrack"; import { userAttributesService } from "../../helpers/user-attributes"; import { filterAttrs } from "../helpers"; import { checkShouldRenderVariants, DEFAULT_INDEX, filterWithCustomTargeting, getBlocksToRender, getPersonalizationScript, getUpdateVisibilityStylesScript, SDKS_REQUIRING_RESET_APPROACH, } from "./helpers"; import type { PersonalizationContainerProps } from "./personalization-container.types"; import { setAttrs } from "../helpers"; function PersonalizationContainer(props: PersonalizationContainerProps) { const rootRef = useRef(null); const [userAttributes, setUserAttributes] = useState(() => userAttributesService.getUserAttributes() ); const [scriptStr, setScriptStr] = useState(() => getPersonalizationScript( props.variants, props.builderBlock?.id || "none", props.builderContext?.rootState?.locale as string | undefined ) ); const [updateVisibilityStylesScript, setUpdateVisibilityStylesScript] = useState(() => getUpdateVisibilityStylesScript( props.variants, props.builderBlock?.id || "none", props.builderContext?.rootState?.locale as string | undefined ) ); const [unsubscribers, setUnsubscribers] = useState(() => []); const [shouldRenderVariants, setShouldRenderVariants] = useState(() => checkShouldRenderVariants( props.variants, getDefaultCanTrack(props.builderContext?.canTrack) ) ); const [shouldResetVariants, setShouldResetVariants] = useState(() => false); function attrs() { return { ...props.attributes, ...{}, [getClassPropName()]: `builder-personalization-container ${ props.attributes[getClassPropName()] || "" }`, }; } function filteredVariants() { return (props.variants || []).filter((variant) => { return filterWithCustomTargeting( { ...(props.builderContext?.rootState?.locale ? { locale: props.builderContext?.rootState?.locale, } : {}), ...(userAttributes as any), }, variant.query, variant.startDate, variant.endDate ); }); } function blocksToRender() { return getBlocksToRender({ variants: props.variants, fallbackBlocks: props.builderBlock?.children, isHydrated: shouldResetVariants, filteredVariants: filteredVariants(), previewingIndex: props.previewingIndex, }); } function hideVariantsStyleString() { return (props.variants || []) .map( (_, index) => `div[data-variant-id="${props.builderBlock?.id}-${index}"] { display: none !important; } ` ) .join(""); } useEffect(() => { setShouldResetVariants(true); const unsub = userAttributesService.subscribeOnUserAttributesChange( (attrs) => { setUserAttributes(attrs); }, { fireImmediately: TARGET === "qwik", } ); if (!(isEditing() || isPreviewing())) { const variant = filteredVariants()[0]; if (rootRef.current) { rootRef.current.dispatchEvent( new CustomEvent("builder.variantLoaded", { detail: { variant: variant || DEFAULT_INDEX, content: props.builderContext?.content, }, bubbles: true, }) ); const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting && rootRef.current) { rootRef.current.dispatchEvent( new CustomEvent("builder.variantDisplayed", { detail: { variant: variant || DEFAULT_INDEX, content: props.builderContext?.content, }, bubbles: true, }) ); } }); }); observer.observe(rootRef.current); } } unsubscribers.push(unsub); }, []); useEffect(() => { return () => { unsubscribers.forEach((unsub) => unsub()); }; }, []); return ( {shouldResetVariants && SDKS_REQUIRING_RESET_APPROACH.includes(TARGET) ? ( ) : null} {(!shouldResetVariants && SDKS_REQUIRING_RESET_APPROACH.includes(TARGET)) || !SDKS_REQUIRING_RESET_APPROACH.includes(TARGET) ? ( <> {shouldRenderVariants ? ( <> {props.variants?.map((variant, index) => ( ))} ) : null} {shouldRenderVariants ? ( ) : null} ) : null} ); } export default PersonalizationContainer;