import { useIsServer, useViewed } from "../../../hooks"; import { User, useUserData } from "../../../user-context"; import "./index.scss"; import { useGleanClick } from "../../../telemetry/glean-context"; import { Status, usePlacement } from "../../../placement-context"; import { Payload as PlacementData } from "../../../../../libs/pong/types"; import { BANNER_SCRIMBA_CLICK, BANNER_SCRIMBA_VIEW, } from "../../../telemetry/constants"; interface PlacementRenderArgs { place: any; extraClassNames?: string[]; click: string; image: string; alt?: string; imageWidth: number; imageHeight: number; copy?: string; cta?: string; user: User; style: object; version?: number; typ: string; heading?: string; showNoAds: boolean; } function viewed(pong?: PlacementData) { pong?.view && navigator.sendBeacon?.( `/pong/viewed?code=${encodeURIComponent(pong?.view)}${ pong?.version ? `&version=${pong.version}` : "" }` ); } export function SidePlacement({ extraClasses = [], }: { extraClasses?: string[]; } = {}) { const placementData = usePlacement(); const { textColor, backgroundColor, textColorDark, backgroundColorDark } = placementData?.side?.colors || {}; const css = Object.fromEntries( [ ["--place-new-side-background-light", backgroundColor], ["--place-new-side-color-light", textColor], [ "--place-new-side-background-dark", backgroundColorDark || backgroundColor, ], ["--place-new-side-color-dark", textColorDark || textColor], ].filter(([_, v]) => Boolean(v)) ); return !placementData?.side ? (
) : placementData.side.cta && placementData.side.heading ? ( ) : ( ); } function TopPlacementFallbackContent() { const gleanClick = useGleanClick(); const observedNode = useViewed(() => { gleanClick(BANNER_SCRIMBA_VIEW); }); const now = Date.now(); return (

Learn front-end development with high quality, interactive courses from{" "} { gleanClick(BANNER_SCRIMBA_CLICK); }} > Scrimba .{" "} {now < Date.parse("2025-01-08") ? "Enroll now and save 25% this New Year!" : "Enroll now!"}

); } export function TopPlacement() { const isServer = useIsServer(); const placementData = usePlacement(); const data = placementData?.hpTop || placementData?.top; const { textColor, backgroundColor, ctaTextColor, ctaBackgroundColor, textColorDark, backgroundColorDark, ctaTextColorDark, ctaBackgroundColorDark, } = data?.colors || {}; const css = Object.fromEntries( [ ["--place-top-background-light", backgroundColor], ["--place-top-color-light", textColor], ["--place-top-cta-background-light", ctaBackgroundColor], ["--place-top-cta-color-light", ctaTextColor], ["--place-top-background-dark", backgroundColorDark || backgroundColor], ["--place-top-color-dark", textColorDark || textColor], [ "--place-top-cta-background-dark", ctaBackgroundColorDark || ctaBackgroundColor, ], ["--place-top-cta-color-dark", ctaTextColorDark || ctaBackgroundColor], ].filter(([_, v]) => Boolean(v)) ); const status = isServer || placementData?.status === Status.loading ? "loading" : data ? "visible" : "fallback"; return (
{isServer || !data ? (
{!isServer && placementData?.status !== Status.loading && ( )}
) : ( )}
); } export function HpMainPlacement() { const placementData = usePlacement(); return HpPlacement({ placementData: placementData?.hpMain, imageWidth: 970, imageHeight: 250, typ: "hp-main", }); } export function HpFooterPlacement() { const placementData = usePlacement(); return HpPlacement({ placementData: placementData?.hpFooter, imageWidth: 728, imageHeight: 90, typ: "hp-footer", }); } function HpPlacement({ placementData, imageWidth, imageHeight, typ, }: { placementData?: PlacementData; imageWidth: number; imageHeight: number; typ: string; }) { const { backgroundColor } = placementData?.colors || {}; const css = Object.fromEntries( [["--place-hp-main-background", backgroundColor]].filter(([_, v]) => Boolean(v) ) ); return !placementData ? (
) : ( ); } export function BottomBanner() { const placementData = usePlacement()?.bottom; const { backgroundColor, textColor } = placementData?.colors || {}; const css = Object.fromEntries( [ ["--place-hp-main-background", backgroundColor], ["--place-bottom-banner-background", backgroundColor], ["--place-bottom-banner-color", textColor], ].filter(([_, v]) => Boolean(v)) ); return placementData ? ( ) : null; } export function PlacementInner({ pong, extraClassNames = [], cta, imageWidth, imageHeight, style, renderer, typ, }: { pong?: PlacementData; extraClassNames?: string[]; cta?: string; imageWidth?: number; imageHeight?: number; style?: object; renderer: (PlacementRenderArgs) => JSX.Element; typ: string; }) { const isServer = useIsServer(); const user = useUserData(); const gleanClick = useGleanClick(); const { plusAvailable } = usePlacement() || {}; const showNoAds = Boolean(user?.isSubscriber || plusAvailable); const place = useViewed(() => { viewed(pong); gleanClick(`pong: pong->viewed ${typ}`); }); const { image, copy, alt, click, version, heading } = pong || {}; return ( <> {!isServer && ((click && image) || pong?.status === Status.empty) && renderer({ place, extraClassNames, click, image, alt, imageWidth, imageHeight, copy, cta, user, style, version, typ, heading, showNoAds, })} ); } function RenderSideOrTopBanner({ place, extraClassNames = [], click, image, alt, imageWidth, imageHeight, copy, cta, user, style, version = 1, typ, showNoAds, }: PlacementRenderArgs) { return (

click ${typ}`} href={`/pong/click?code=${encodeURIComponent( click )}&version=${version}`} target="_blank" rel="sponsored noreferrer" > {alt {copy} {cta && ( click ${typ}`} href={`/pong/click?code=${encodeURIComponent( click )}&version=${version}`} target="_blank" rel="sponsored noreferrer" > {cta} )} Ad

{showNoAds && ( settings" : "pong->plus") } href={ user?.isSubscriber ? "/en-US/plus/settings?ref=nope" : "/en-US/plus?ref=nope" } > Don't want to see ads? )}
); } function RenderHpPlacement({ place, extraClassNames = [], click, image, alt, imageWidth, imageHeight, copy, style, version = 1, typ, }: PlacementRenderArgs) { return (
click ${typ}`} href={`/pong/click?code=${encodeURIComponent( click )}&version=${version}`} target="_blank" rel="sponsored noreferrer" > {alt Ad {" "}
); } function RenderBottomBanner({ place, extraClassNames = [], click, image, alt, imageWidth, imageHeight, copy, user, style, version = 1, typ, showNoAds, }: PlacementRenderArgs) { return (
click ${typ}`} href={`/pong/click?code=${encodeURIComponent( click )}&version=${version}`} target="_blank" rel="sponsored noreferrer" > {alt Ad
); } function RenderNewSideBanner({ place, extraClassNames = [], click, image, alt, imageWidth, imageHeight, copy, cta, user, style, version = 1, typ, heading, showNoAds, }: PlacementRenderArgs) { return (
click ${typ}`} href={`/pong/click?code=${encodeURIComponent( click )}&version=${version}`} target="_blank" rel="sponsored noreferrer" > {alt
{heading} {copy} {cta && {cta}}
Ad
{showNoAds && ( settings" : "pong->plus") } href={ user?.isSubscriber ? "/en-US/plus/settings?ref=nope" : "/en-US/plus?ref=nope" } > Don't want to see ads? )}
); }