| Server IP : 146.59.209.152 / Your IP : 216.73.217.111 Web Server : Apache System : Linux webm009.cluster131.gra.hosting.ovh.net 6.18.42-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Wed Aug 5 15:59:48 CEST 2026 x86_64 User : monpetu ( 144298) PHP Version : 7.4.33 Disable Function : _dyuweyrj4,_dyuweyrj4r,dl MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /home/monpetu/www/ipprint/wp-content/plugins/woocommerce-payments/dist/chunks/ |
Upload File : |
{"version":3,"file":"chunks/252.js?ver=f60c80dbf8c019cc3c8e","mappings":"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","sources":["webpack://woocommerce-payments/./client/components/chip/index.tsx","webpack://woocommerce-payments/./client/components/spotlight/index.tsx","webpack://woocommerce-payments/./client/data/pm-promotions/action-types.ts","webpack://woocommerce-payments/./client/data/pm-promotions/actions.ts","webpack://woocommerce-payments/./client/data/pm-promotions/hooks.ts","webpack://woocommerce-payments/./client/data/pm-promotions/reducer.ts","webpack://woocommerce-payments/./client/data/pm-promotions/resolvers.ts","webpack://woocommerce-payments/./client/data/pm-promotions/selectors.ts","webpack://woocommerce-payments/./client/data/pm-promotions/store.js","webpack://woocommerce-payments/./client/promotions/spotlight/index.tsx"],"sourcesContent":["/** @format **/\n\n/**\n * External dependencies\n */\nimport React from 'react';\nimport { Icon } from '@wordpress/icons';\nimport clsx from 'clsx';\n\n/**\n * Internal dependencies\n */\nimport './style.scss';\nimport { HoverTooltip } from 'wcpay/components/tooltip';\n\nexport type ChipType = 'primary' | 'success' | 'light' | 'warning' | 'alert';\n\ninterface Props {\n\tmessage: string;\n\ttype?: ChipType;\n\tclassName?: string;\n\ttooltip?: string;\n\ticon?: React.JSX.Element;\n}\nconst Chip: React.FC< React.PropsWithChildren< Props > > = ( {\n\tmessage,\n\ttype = 'primary',\n\tclassName,\n\ttooltip,\n\ticon,\n} ) => {\n\tconst classNames = clsx(\n\t\t'chip',\n\t\t`chip-${ type }`,\n\t\ticon && 'chip-has-icon',\n\t\tclassName\n\t);\n\n\tconst content = (\n\t\t<>\n\t\t\t{ icon && <Icon icon={ icon } size={ 16 } /> }\n\t\t\t{ message }\n\t\t</>\n\t);\n\n\tif ( tooltip ) {\n\t\treturn (\n\t\t\t<HoverTooltip content={ tooltip }>\n\t\t\t\t<span className={ classNames }>{ content }</span>\n\t\t\t</HoverTooltip>\n\t\t);\n\t}\n\treturn <span className={ classNames }>{ content }</span>;\n};\n\nexport default Chip;\n","/**\n * External dependencies\n */\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n\tCard,\n\tCardBody,\n\tCardHeader,\n\tCardMedia,\n\tCardFooter,\n\tButton,\n\tFlex,\n\tIcon,\n} from '@wordpress/components';\nimport { closeSmall } from '@wordpress/icons';\nimport { __, sprintf } from '@wordpress/i18n';\nimport { speak } from '@wordpress/a11y';\n\n/**\n * Internal dependencies\n */\nimport { SpotlightProps } from './types';\nimport Chip, { ChipType } from 'components/chip';\nimport { sanitizeHTML } from 'utils/sanitize';\nimport './style.scss';\n\n/**\n * Valid chip types for the badge.\n */\nconst validBadgeTypes: ChipType[] = [\n\t'primary',\n\t'success',\n\t'light',\n\t'warning',\n\t'alert',\n];\n\n/**\n * Get a valid badge type, defaulting to 'success' if invalid or not provided.\n *\n * @param type - The badge type to validate.\n * @return A valid ChipType.\n */\nconst getValidBadgeType = ( type?: ChipType ): ChipType => {\n\tif ( type && validBadgeTypes.includes( type ) ) {\n\t\treturn type;\n\t}\n\treturn 'success';\n};\n\nconst Spotlight: React.FC< SpotlightProps > = ( {\n\tbadge,\n\tbadgeType,\n\theading,\n\tdescription,\n\tfootnote,\n\timage,\n\ticon,\n\tprimaryButtonLabel,\n\tonPrimaryClick,\n\tsecondaryButtonLabel,\n\tonSecondaryClick,\n\tonDismiss,\n\tonView,\n\tshowImmediately = false,\n\tshowDelayMs = 4000,\n\treverseButtons = false,\n} ) => {\n\tconst validBadgeType = getValidBadgeType( badgeType );\n\tconst [ isVisible, setIsVisible ] = useState( false );\n\tconst [ isAnimatingIn, setIsAnimatingIn ] = useState( false );\n\tconst closeTimeoutRef = useRef< ReturnType< typeof setTimeout > | null >(\n\t\tnull\n\t);\n\tconst dialogRef = useRef< HTMLDivElement >( null );\n\tconst previouslyFocusedElementRef = useRef< HTMLElement | null >( null );\n\n\tuseEffect( () => {\n\t\tif ( showImmediately ) {\n\t\t\tsetIsVisible( true );\n\t\t\tsetIsAnimatingIn( true );\n\t\t\treturn;\n\t\t}\n\n\t\t// Show the spotlight after a delay\n\t\tconst timer = setTimeout( () => {\n\t\t\tsetIsVisible( true );\n\t\t\t// Double RAF to ensure browser paints initial state before animating\n\t\t\trequestAnimationFrame( () => {\n\t\t\t\trequestAnimationFrame( () => {\n\t\t\t\t\tsetIsAnimatingIn( true );\n\t\t\t\t} );\n\t\t\t} );\n\t\t}, showDelayMs );\n\n\t\treturn () => clearTimeout( timer );\n\t}, [ showImmediately, showDelayMs ] );\n\n\t// Cleanup close timeout on unmount\n\tuseEffect( () => {\n\t\treturn () => {\n\t\t\tif ( closeTimeoutRef.current ) {\n\t\t\t\tclearTimeout( closeTimeoutRef.current );\n\t\t\t}\n\t\t};\n\t}, [] );\n\n\t// Call onView and announce to screen readers when spotlight becomes visible\n\tuseEffect( () => {\n\t\tif ( isAnimatingIn ) {\n\t\t\t// Announce to screen readers that a dialog has appeared\n\t\t\tspeak(\n\t\t\t\tsprintf(\n\t\t\t\t\t/* translators: %s: heading text of the spotlight dialog */\n\t\t\t\t\t__( 'Dialog opened: %s', 'woocommerce-payments' ),\n\t\t\t\t\theading\n\t\t\t\t),\n\t\t\t\t'polite'\n\t\t\t);\n\n\t\t\tif ( onView ) {\n\t\t\t\tonView();\n\t\t\t}\n\t\t}\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [ isAnimatingIn ] );\n\n\tconst handleClose = useCallback(\n\t\t( shouldDismiss = true ) => {\n\t\t\tsetIsAnimatingIn( false );\n\t\t\t// Wait for animation to complete before hiding\n\t\t\tcloseTimeoutRef.current = setTimeout( () => {\n\t\t\t\tsetIsVisible( false );\n\t\t\t\tif ( shouldDismiss ) {\n\t\t\t\t\tonDismiss();\n\t\t\t\t}\n\t\t\t}, 300 );\n\t\t},\n\t\t[ onDismiss ]\n\t);\n\n\t// Focus management: save previous focus, focus dialog, handle Escape, trap focus, restore on close\n\tuseEffect( () => {\n\t\tif ( ! isVisible || ! dialogRef.current ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst dialog = dialogRef.current;\n\t\tconst ownerDocument = dialog.ownerDocument;\n\n\t\t// Save the currently focused element to restore later\n\t\tpreviouslyFocusedElementRef.current =\n\t\t\townerDocument.activeElement as HTMLElement;\n\n\t\t// Focus the dialog\n\t\tdialog.focus();\n\n\t\tconst handleKeyDown = ( event: KeyboardEvent ) => {\n\t\t\tif ( event.key === 'Escape' ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\thandleClose();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Focus trapping\n\t\t\tif ( event.key === 'Tab' ) {\n\t\t\t\tconst focusableElements =\n\t\t\t\t\tdialog.querySelectorAll< HTMLElement >(\n\t\t\t\t\t\t'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n\t\t\t\t\t);\n\t\t\t\tconst firstElement = focusableElements[ 0 ];\n\t\t\t\tconst lastElement =\n\t\t\t\t\tfocusableElements[ focusableElements.length - 1 ];\n\t\t\t\tconst activeElement = ownerDocument.activeElement;\n\n\t\t\t\tif ( event.shiftKey && activeElement === firstElement ) {\n\t\t\t\t\t// Shift + Tab: if on first element, wrap to last\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tlastElement?.focus();\n\t\t\t\t} else if (\n\t\t\t\t\t! event.shiftKey &&\n\t\t\t\t\tactiveElement === lastElement\n\t\t\t\t) {\n\t\t\t\t\t// Tab: if on last element, wrap to first\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tfirstElement?.focus();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\townerDocument.addEventListener( 'keydown', handleKeyDown );\n\n\t\treturn () => {\n\t\t\townerDocument.removeEventListener( 'keydown', handleKeyDown );\n\t\t\t// Restore focus to previously focused element\n\t\t\tpreviouslyFocusedElementRef.current?.focus();\n\t\t};\n\t}, [ isVisible, handleClose ] );\n\n\tconst handlePrimaryClick = () => {\n\t\tonPrimaryClick();\n\t\t// Close without calling onDismiss - the backend handles dismissal on activation.\n\t\thandleClose( false );\n\t};\n\n\tif ( ! isVisible ) {\n\t\treturn null;\n\t}\n\n\t// Define buttons to avoid duplication\n\tconst primaryButton = (\n\t\t<Button\n\t\t\tclassName=\"wcpay-spotlight__primary-btn\"\n\t\t\tvariant=\"secondary\"\n\t\t\tonClick={ handlePrimaryClick }\n\t\t\tsize=\"compact\"\n\t\t>\n\t\t\t{ primaryButtonLabel }\n\t\t</Button>\n\t);\n\n\tconst secondaryButton = secondaryButtonLabel && (\n\t\t<Button\n\t\t\tclassName=\"wcpay-spotlight__secondary-btn\"\n\t\t\tvariant=\"tertiary\"\n\t\t\tonClick={ onSecondaryClick }\n\t\t\tsize=\"compact\"\n\t\t>\n\t\t\t{ secondaryButtonLabel }\n\t\t</Button>\n\t);\n\n\treturn (\n\t\t<div\n\t\t\tclassName={ `wcpay-spotlight ${\n\t\t\t\tisAnimatingIn ? 'wcpay-spotlight--visible' : ''\n\t\t\t}` }\n\t\t>\n\t\t\t<div\n\t\t\t\tref={ dialogRef }\n\t\t\t\trole=\"dialog\"\n\t\t\t\taria-modal=\"true\"\n\t\t\t\taria-labelledby=\"spotlight-heading\"\n\t\t\t\ttabIndex={ -1 }\n\t\t\t\tclassName=\"wcpay-spotlight__container\"\n\t\t\t>\n\t\t\t\t<Card\n\t\t\t\t\tclassName={ `wcpay-spotlight__card ${\n\t\t\t\t\t\timage ? 'has-image' : ''\n\t\t\t\t\t} ${ icon ? 'has-icon' : '' }` }\n\t\t\t\t\televation={ 2 }\n\t\t\t\t>\n\t\t\t\t\t{ image && (\n\t\t\t\t\t\t<CardMedia className=\"wcpay-spotlight__image\">\n\t\t\t\t\t\t\t{ typeof image === 'string' ? (\n\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\tsrc={ image }\n\t\t\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\trole=\"presentation\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\timage\n\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t</CardMedia>\n\t\t\t\t\t) }\n\n\t\t\t\t\t<CardHeader\n\t\t\t\t\t\tisBorderless={ true }\n\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\tclassName=\"wcpay-spotlight__header\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Flex\n\t\t\t\t\t\t\tclassName=\"wcpay-spotlight__controls\"\n\t\t\t\t\t\t\tjustify=\"space-between\"\n\t\t\t\t\t\t\talign=\"center\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{ /* When no image and no icon: show badge if available, otherwise show heading */ }\n\t\t\t\t\t\t\t{ ! image && ! icon && badge && (\n\t\t\t\t\t\t\t\t<div className=\"wcpay-spotlight__badge\">\n\t\t\t\t\t\t\t\t\t<Chip\n\t\t\t\t\t\t\t\t\t\tmessage={ badge }\n\t\t\t\t\t\t\t\t\t\ttype={ validBadgeType }\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t{ ! image && ! icon && ! badge && (\n\t\t\t\t\t\t\t\t<h2\n\t\t\t\t\t\t\t\t\tid=\"spotlight-heading\"\n\t\t\t\t\t\t\t\t\tclassName=\"wcpay-spotlight__heading\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{ heading }\n\t\t\t\t\t\t\t\t</h2>\n\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t{ /* Spacer when image or icon is present */ }\n\t\t\t\t\t\t\t{ ( image || icon ) && <span /> }\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tclassName=\"wcpay-spotlight__close-btn\"\n\t\t\t\t\t\t\t\tlabel={ __( 'Close', 'woocommerce-payments' ) }\n\t\t\t\t\t\t\t\ticon={\n\t\t\t\t\t\t\t\t\t<Icon\n\t\t\t\t\t\t\t\t\t\ticon={ closeSmall }\n\t\t\t\t\t\t\t\t\t\tviewBox=\"6 4 12 14\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ticonSize={ 16 }\n\t\t\t\t\t\t\t\tonClick={ () => handleClose() }\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</Flex>\n\t\t\t\t\t</CardHeader>\n\n\t\t\t\t\t<CardBody className=\"wcpay-spotlight__body\" size=\"small\">\n\t\t\t\t\t\t{ /* Render icon if provided (small icon in corner, not full-width) */ }\n\t\t\t\t\t\t{ icon && (\n\t\t\t\t\t\t\t<div className=\"wcpay-spotlight__icon\">\n\t\t\t\t\t\t\t\t{ icon }\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t) }\n\t\t\t\t\t\t{ /* When image present OR when no image but badge is in header: show badge in body only if image */ }\n\t\t\t\t\t\t{ image && badge && (\n\t\t\t\t\t\t\t<div className=\"wcpay-spotlight__badge\">\n\t\t\t\t\t\t\t\t<Chip\n\t\t\t\t\t\t\t\t\tmessage={ badge }\n\t\t\t\t\t\t\t\t\ttype={ validBadgeType }\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t) }\n\t\t\t\t\t\t{ /* When no image/icon and badge shown in header: show heading in body */ }\n\t\t\t\t\t\t{ /* When image or icon present: always show heading in body */ }\n\t\t\t\t\t\t{ /* When no image/icon and no badge: heading already in header, don't duplicate */ }\n\t\t\t\t\t\t{ ( image || icon || badge ) && (\n\t\t\t\t\t\t\t<h2\n\t\t\t\t\t\t\t\tid=\"spotlight-heading\"\n\t\t\t\t\t\t\t\tclassName=\"wcpay-spotlight__heading\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{ heading }\n\t\t\t\t\t\t\t</h2>\n\t\t\t\t\t\t) }\n\t\t\t\t\t\t{ typeof description === 'string' ? (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName=\"wcpay-spotlight__description\"\n\t\t\t\t\t\t\t\t// eslint-disable-next-line react/no-danger\n\t\t\t\t\t\t\t\tdangerouslySetInnerHTML={ sanitizeHTML(\n\t\t\t\t\t\t\t\t\tdescription\n\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<div className=\"wcpay-spotlight__description\">\n\t\t\t\t\t\t\t\t{ description }\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t) }\n\t\t\t\t\t\t{ footnote &&\n\t\t\t\t\t\t\t( typeof footnote === 'string' ? (\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tclassName=\"wcpay-spotlight__footnote\"\n\t\t\t\t\t\t\t\t\t// eslint-disable-next-line react/no-danger\n\t\t\t\t\t\t\t\t\tdangerouslySetInnerHTML={ sanitizeHTML(\n\t\t\t\t\t\t\t\t\t\tfootnote\n\t\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<div className=\"wcpay-spotlight__footnote\">\n\t\t\t\t\t\t\t\t\t{ footnote }\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t) ) }\n\t\t\t\t\t</CardBody>\n\n\t\t\t\t\t<CardFooter\n\t\t\t\t\t\tisBorderless={ true }\n\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\tclassName=\"wcpay-spotlight__footer\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Flex justify=\"flex-start\" gap={ 3 }>\n\t\t\t\t\t\t\t{ reverseButtons ? (\n\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t{ primaryButton }\n\t\t\t\t\t\t\t\t\t{ secondaryButton }\n\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t{ secondaryButton }\n\t\t\t\t\t\t\t\t\t{ primaryButton }\n\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t</Flex>\n\t\t\t\t\t</CardFooter>\n\t\t\t\t</Card>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n\nexport default Spotlight;\n","/** @format */\n\nexport enum ACTION_TYPES {\n\tSET_PM_PROMOTIONS = 'SET_PM_PROMOTIONS',\n\tSET_ERROR_FOR_PM_PROMOTIONS = 'SET_ERROR_FOR_PM_PROMOTIONS',\n}\n","/** @format */\n\n/**\n * External dependencies\n */\nimport { apiFetch } from '@wordpress/data-controls';\nimport { controls } from '@wordpress/data';\nimport { __ } from '@wordpress/i18n';\n\n/**\n * Internal dependencies\n */\nimport { ACTION_TYPES } from './action-types';\nimport {\n\tPmPromotionsData,\n\tUpdatePmPromotionsAction,\n\tErrorPmPromotionsAction,\n} from './types';\nimport { ApiError } from '../../types/errors';\nimport { NAMESPACE } from '../constants';\nimport { PM_PROMOTIONS_STORE_NAME as STORE_NAME } from '../store-names';\n\n/**\n * Type guard to check if an error is an ApiError.\n */\nfunction isApiError( error: unknown ): error is ApiError {\n\treturn (\n\t\ttypeof error === 'object' &&\n\t\terror !== null &&\n\t\t'code' in error &&\n\t\ttypeof ( error as ApiError ).code === 'string'\n\t);\n}\n\n/**\n * Normalizes an unknown error to an ApiError.\n */\nfunction normalizeError( error: unknown ): ApiError {\n\tif ( isApiError( error ) ) {\n\t\treturn error;\n\t}\n\treturn {\n\t\tcode: 'unknown_error',\n\t};\n}\n\nexport function updatePmPromotions(\n\tdata: PmPromotionsData\n): UpdatePmPromotionsAction {\n\treturn {\n\t\ttype: ACTION_TYPES.SET_PM_PROMOTIONS,\n\t\tdata,\n\t};\n}\n\nexport function updateErrorForPmPromotions(\n\terror: ApiError\n): ErrorPmPromotionsAction {\n\treturn {\n\t\ttype: ACTION_TYPES.SET_ERROR_FOR_PM_PROMOTIONS,\n\t\terror,\n\t};\n}\n\n/**\n * Activate a PM promotion.\n *\n * @param {string} identifier The promotion identifier.\n */\nexport function* activatePmPromotion( identifier: string ): unknown {\n\tconst path = `${ NAMESPACE }/pm-promotions/${ identifier }/activate`;\n\n\ttry {\n\t\tyield apiFetch( {\n\t\t\tpath,\n\t\t\tmethod: 'POST',\n\t\t} );\n\n\t\tyield controls.dispatch(\n\t\t\t'core/notices',\n\t\t\t'createSuccessNotice',\n\t\t\t__( 'Promotion activated successfully!', 'woocommerce-payments' )\n\t\t);\n\n\t\t// Refetch promotions to update the list.\n\t\tyield controls.dispatch(\n\t\t\tSTORE_NAME,\n\t\t\t'invalidateResolution',\n\t\t\t'getPmPromotions',\n\t\t\t[]\n\t\t);\n\t} catch ( e ) {\n\t\tyield controls.dispatch(\n\t\t\t'core/notices',\n\t\t\t'createErrorNotice',\n\t\t\t__(\n\t\t\t\t'Error activating promotion. Please try again.',\n\t\t\t\t'woocommerce-payments'\n\t\t\t)\n\t\t);\n\t\tyield controls.dispatch(\n\t\t\tSTORE_NAME,\n\t\t\t'updateErrorForPmPromotions',\n\t\t\tnormalizeError( e )\n\t\t);\n\t}\n}\n\n/**\n * Dismiss a PM promotion.\n *\n * @param {string} id The promotion unique identifier.\n */\nexport function* dismissPmPromotion( id: string ): unknown {\n\tconst path = `${ NAMESPACE }/pm-promotions/${ id }/dismiss`;\n\n\ttry {\n\t\tyield apiFetch( {\n\t\t\tpath,\n\t\t\tmethod: 'POST',\n\t\t} );\n\n\t\tyield controls.dispatch(\n\t\t\t'core/notices',\n\t\t\t'createSuccessNotice',\n\t\t\t__( 'Promotion dismissed.', 'woocommerce-payments' )\n\t\t);\n\n\t\t// Refetch promotions to update the list.\n\t\tyield controls.dispatch(\n\t\t\tSTORE_NAME,\n\t\t\t'invalidateResolution',\n\t\t\t'getPmPromotions',\n\t\t\t[]\n\t\t);\n\t} catch ( e ) {\n\t\tyield controls.dispatch(\n\t\t\t'core/notices',\n\t\t\t'createErrorNotice',\n\t\t\t__(\n\t\t\t\t'Error dismissing promotion. Please try again.',\n\t\t\t\t'woocommerce-payments'\n\t\t\t)\n\t\t);\n\t\tyield controls.dispatch(\n\t\t\tSTORE_NAME,\n\t\t\t'updateErrorForPmPromotions',\n\t\t\tnormalizeError( e )\n\t\t);\n\t}\n}\n","/** @format */\n\n/**\n * External dependencies\n */\nimport { useSelect, useDispatch } from '@wordpress/data';\n\n/**\n * Internal dependencies\n */\nimport { STORE_NAME } from './store';\nimport { PmPromotionsResponse, PmPromotionActions } from './types';\n\n/**\n * Hook to retrieve PM promotions data.\n *\n * @return {PmPromotionsResponse} The promotions data, error, and loading state.\n */\nexport const usePmPromotions = (): PmPromotionsResponse =>\n\tuseSelect( ( select ) => {\n\t\tconst { getPmPromotions, getPmPromotionsError, isResolving } =\n\t\t\tselect( STORE_NAME );\n\n\t\treturn {\n\t\t\tpmPromotions: getPmPromotions(),\n\t\t\tpmPromotionsError: getPmPromotionsError(),\n\t\t\tisLoading: isResolving( 'getPmPromotions' ),\n\t\t};\n\t} );\n\n/**\n * Hook to get PM promotion actions (activate and dismiss).\n *\n * @return {PmPromotionActions} Object with activatePmPromotion and dismissPmPromotion functions.\n */\nexport const usePmPromotionActions = (): PmPromotionActions => {\n\tconst { activatePmPromotion, dismissPmPromotion } =\n\t\tuseDispatch( STORE_NAME );\n\n\treturn {\n\t\tactivatePmPromotion,\n\t\tdismissPmPromotion,\n\t};\n};\n","/** @format */\n\n/**\n * Internal dependencies\n */\nimport { ACTION_TYPES } from './action-types';\nimport { PmPromotionsState, PmPromotionsActions } from './types';\n\nconst defaultState: PmPromotionsState = {\n\tpmPromotions: undefined,\n\tpmPromotionsError: undefined,\n};\n\nexport const receivePmPromotions = (\n\tstate: PmPromotionsState = defaultState,\n\taction: PmPromotionsActions\n): PmPromotionsState => {\n\tswitch ( action.type ) {\n\t\tcase ACTION_TYPES.SET_PM_PROMOTIONS:\n\t\t\treturn {\n\t\t\t\t...state,\n\t\t\t\tpmPromotions: action.data,\n\t\t\t\tpmPromotionsError: undefined,\n\t\t\t};\n\t\tcase ACTION_TYPES.SET_ERROR_FOR_PM_PROMOTIONS:\n\t\t\treturn {\n\t\t\t\t...state,\n\t\t\t\tpmPromotions: undefined,\n\t\t\t\tpmPromotionsError: action.error,\n\t\t\t};\n\t}\n\n\treturn state;\n};\n\nexport default receivePmPromotions;\n","/** @format */\n\n/**\n * External dependencies\n */\nimport { apiFetch } from '@wordpress/data-controls';\nimport { controls } from '@wordpress/data';\nimport { __ } from '@wordpress/i18n';\n\n/**\n * Internal dependencies\n */\nimport { NAMESPACE } from '../constants';\nimport { PM_PROMOTIONS_STORE_NAME as STORE_NAME } from '../store-names';\nimport { PmPromotion, PmPromotionsData } from './types';\nimport { ApiError } from '../../types/errors';\n\n/**\n * Type guard to check if an object is a valid PmPromotion.\n */\nfunction isPmPromotion( value: unknown ): value is PmPromotion {\n\tif ( typeof value !== 'object' || value === null ) {\n\t\treturn false;\n\t}\n\tconst obj = value as Record< string, unknown >;\n\treturn (\n\t\ttypeof obj.id === 'string' &&\n\t\ttypeof obj.promo_id === 'string' &&\n\t\ttypeof obj.payment_method === 'string' &&\n\t\ttypeof obj.payment_method_title === 'string' &&\n\t\ttypeof obj.type === 'string' &&\n\t\t( obj.type === 'spotlight' || obj.type === 'badge' ) &&\n\t\ttypeof obj.title === 'string' &&\n\t\ttypeof obj.description === 'string' &&\n\t\ttypeof obj.cta_label === 'string' &&\n\t\ttypeof obj.tc_url === 'string' &&\n\t\ttypeof obj.tc_label === 'string'\n\t);\n}\n\n/**\n * Type guard to check if a value is valid PmPromotionsData.\n */\nfunction isPmPromotionsData( value: unknown ): value is PmPromotionsData {\n\treturn Array.isArray( value ) && value.every( isPmPromotion );\n}\n\n/**\n * Type guard to check if an error is an ApiError.\n */\nfunction isApiError( error: unknown ): error is ApiError {\n\treturn typeof error === 'object' && error !== null && 'code' in error;\n}\n\n/**\n * Normalizes an unknown error to an ApiError.\n */\nfunction normalizeError( error: unknown ): ApiError {\n\tif ( isApiError( error ) ) {\n\t\treturn error;\n\t}\n\treturn {\n\t\tcode: 'unknown_error',\n\t};\n}\n\n/**\n * Retrieve PM promotions data.\n */\nexport function* getPmPromotions(): unknown {\n\tconst path = `${ NAMESPACE }/pm-promotions`;\n\n\ttry {\n\t\tconst result = yield apiFetch( { path } );\n\n\t\tif ( ! isPmPromotionsData( result ) ) {\n\t\t\tthrow new Error( 'Invalid promotions data received from API' );\n\t\t}\n\n\t\tyield controls.dispatch( STORE_NAME, 'updatePmPromotions', result );\n\t} catch ( e ) {\n\t\tyield controls.dispatch(\n\t\t\t'core/notices',\n\t\t\t'createErrorNotice',\n\t\t\t__(\n\t\t\t\t'Error retrieving promotions. Please try again later.',\n\t\t\t\t'woocommerce-payments'\n\t\t\t)\n\t\t);\n\t\tyield controls.dispatch(\n\t\t\tSTORE_NAME,\n\t\t\t'updateErrorForPmPromotions',\n\t\t\tnormalizeError( e )\n\t\t);\n\t}\n}\n","/** @format */\n\n/**\n * Internal dependencies\n */\nimport { PmPromotionsState, PmPromotionsData } from './types';\nimport { ApiError } from '../../types/errors';\n\n// Type for the full Redux state with pmPromotions slice.\ninterface State {\n\tpmPromotions: PmPromotionsState;\n}\n\n/**\n * Retrieves the PM promotions array from the state.\n *\n * @param {State} state The full Redux state.\n *\n * @return {PmPromotionsData} Array of promotions, or empty array if not loaded.\n */\nexport const getPmPromotions = ( state: State ): PmPromotionsData => {\n\treturn state.pmPromotions?.pmPromotions ?? ( [] as PmPromotionsData );\n};\n\n/**\n * Retrieves any error that occurred while fetching PM promotions.\n *\n * @param {State} state The full Redux state.\n *\n * @return {ApiError | undefined} The error or undefined.\n */\nexport const getPmPromotionsError = ( state: State ): ApiError | undefined => {\n\treturn state.pmPromotions?.pmPromotionsError;\n};\n","/** @format */\n\n/**\n * External dependencies\n */\nimport { createReduxStore, register, combineReducers } from '@wordpress/data';\nimport { controls } from '@wordpress/data-controls';\n\n/**\n * Internal dependencies\n */\nimport reducer from './reducer';\nimport * as selectors from './selectors';\nimport * as actions from './actions';\nimport * as resolvers from './resolvers';\nimport { PM_PROMOTIONS_STORE_NAME } from '../store-names';\n\nexport const STORE_NAME = PM_PROMOTIONS_STORE_NAME;\n\n// The reducer is nested under its slice key so selectors keep reading\n// `state.pmPromotions.…`, exactly as they did under the old combined store.\nexport const store = createReduxStore( STORE_NAME, {\n\treducer: combineReducers( { pmPromotions: reducer } ),\n\tactions,\n\tselectors,\n\tresolvers,\n\tcontrols,\n} );\n\nregister( store );\n","/** @format */\n\n/**\n * External dependencies\n */\nimport React, { useCallback, useMemo } from 'react';\n\n/**\n * Internal dependencies\n */\nimport Spotlight from 'components/spotlight';\nimport {\n\tusePmPromotions,\n\tusePmPromotionActions,\n} from 'wcpay/data/pm-promotions';\nimport { PmPromotion } from 'wcpay/data/pm-promotions/types';\nimport { recordEvent } from 'tracks';\n\n/**\n * Determine a human-readable source identifier based on the current page.\n *\n * @return {string} Source identifier for tracking.\n */\nconst getPageSource = (): string => {\n\tconst path = window.location.pathname + window.location.search;\n\n\tif ( path.includes( 'path=%2Fpayments%2Foverview' ) ) {\n\t\treturn 'wcpay-overview';\n\t}\n\tif ( path.includes( 'path=%2Fpayments%2Fsettings' ) ) {\n\t\treturn 'wcpay-settings';\n\t}\n\tif (\n\t\tpath.includes( 'page=wc-settings' ) &&\n\t\tpath.includes( 'tab=checkout' )\n\t) {\n\t\treturn 'wc-settings-payments';\n\t}\n\n\treturn 'unknown';\n};\n\n/**\n * Container component that fetches promotions and renders the Spotlight component.\n *\n * This component:\n * - Fetches promotions from the API\n * - Filters for 'spotlight' type promotions\n * - Handles activation and dismissal of promotions\n */\nconst SpotlightPromotion: React.FC = () => {\n\tconst { pmPromotions, isLoading } = usePmPromotions();\n\tconst { activatePmPromotion, dismissPmPromotion } = usePmPromotionActions();\n\n\t// Memoize the spotlight promotion lookup to prevent recalculation on every render.\n\tconst spotlightPromotion: PmPromotion | undefined = useMemo(\n\t\t() => pmPromotions?.find( ( promo ) => promo.type === 'spotlight' ),\n\t\t[ pmPromotions ]\n\t);\n\n\t/**\n\t * Get common event properties for tracking.\n\t * Memoized to maintain reference equality.\n\t */\n\tconst getEventProperties = useCallback(\n\t\t() => ( {\n\t\t\tpromo_id: spotlightPromotion?.promo_id,\n\t\t\tpayment_method: spotlightPromotion?.payment_method,\n\t\t\tdisplay_context: 'spotlight',\n\t\t\tsource: getPageSource(),\n\t\t\tpath: window.location.pathname + window.location.search,\n\t\t} ),\n\t\t[ spotlightPromotion?.promo_id, spotlightPromotion?.payment_method ]\n\t);\n\n\tconst handleView = useCallback( () => {\n\t\trecordEvent(\n\t\t\t'wcpay_payment_method_promotion_view',\n\t\t\tgetEventProperties()\n\t\t);\n\t}, [ getEventProperties ] );\n\n\tconst handlePrimaryClick = useCallback( () => {\n\t\tif ( ! spotlightPromotion ) return;\n\t\trecordEvent(\n\t\t\t'wcpay_payment_method_promotion_activate_click',\n\t\t\tgetEventProperties()\n\t\t);\n\t\tactivatePmPromotion( spotlightPromotion.id );\n\t}, [ getEventProperties, activatePmPromotion, spotlightPromotion ] );\n\n\tconst handleSecondaryClick = useCallback( () => {\n\t\tif ( ! spotlightPromotion ) return;\n\t\trecordEvent( 'wcpay_payment_method_promotion_link_click', {\n\t\t\t...getEventProperties(),\n\t\t\tlink_type: 'terms',\n\t\t} );\n\t\tif ( spotlightPromotion.tc_url ) {\n\t\t\ttry {\n\t\t\t\tconst parsedUrl = new URL( spotlightPromotion.tc_url );\n\t\t\t\tif (\n\t\t\t\t\tparsedUrl.protocol === 'https:' ||\n\t\t\t\t\tparsedUrl.protocol === 'http:'\n\t\t\t\t) {\n\t\t\t\t\twindow.open(\n\t\t\t\t\t\tspotlightPromotion.tc_url,\n\t\t\t\t\t\t'_blank',\n\t\t\t\t\t\t'noopener,noreferrer'\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Invalid URL, don't open\n\t\t\t}\n\t\t}\n\t}, [ getEventProperties, spotlightPromotion ] );\n\n\tconst handleDismiss = useCallback( () => {\n\t\tif ( ! spotlightPromotion ) return;\n\t\trecordEvent(\n\t\t\t'wcpay_payment_method_promotion_dismiss_click',\n\t\t\tgetEventProperties()\n\t\t);\n\t\tdismissPmPromotion( spotlightPromotion.id );\n\t}, [ getEventProperties, dismissPmPromotion, spotlightPromotion ] );\n\n\t// Don't render if data is still loading.\n\tif ( isLoading ) {\n\t\treturn null;\n\t}\n\n\t// Don't render if no promotions available.\n\tif ( ! pmPromotions || pmPromotions.length === 0 ) {\n\t\treturn null;\n\t}\n\n\t// No spotlight promotion available.\n\tif ( ! spotlightPromotion ) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<Spotlight\n\t\t\tbadge={ spotlightPromotion.badge_text }\n\t\t\tbadgeType={ spotlightPromotion.badge_type }\n\t\t\theading={ spotlightPromotion.title }\n\t\t\tdescription={ spotlightPromotion.description }\n\t\t\tfootnote={ spotlightPromotion.footnote }\n\t\t\timage={ spotlightPromotion.image }\n\t\t\tprimaryButtonLabel={ spotlightPromotion.cta_label }\n\t\t\tonPrimaryClick={ handlePrimaryClick }\n\t\t\tsecondaryButtonLabel={ spotlightPromotion.tc_label }\n\t\t\tonSecondaryClick={ handleSecondaryClick }\n\t\t\tonDismiss={ handleDismiss }\n\t\t\tonView={ handleView }\n\t\t/>\n\t);\n};\n\nexport default SpotlightPromotion;\n"],"names":["Chip","message","type","className","tooltip","icon","classNames","clsx","content","_jsxs","_Fragment","children","_jsx","Icon","size","HoverTooltip","validBadgeTypes","Spotlight","badge","badgeType","heading","description","footnote","image","primaryButtonLabel","onPrimaryClick","secondaryButtonLabel","onSecondaryClick","onDismiss","onView","showImmediately","showDelayMs","reverseButtons","validBadgeType","includes","isVisible","setIsVisible","useState","isAnimatingIn","setIsAnimatingIn","closeTimeoutRef","useRef","dialogRef","previouslyFocusedElementRef","useEffect","timer","setTimeout","requestAnimationFrame","clearTimeout","current","speak","sprintf","__","handleClose","useCallback","shouldDismiss","dialog","ownerDocument","activeElement","focus","handleKeyDown","event","key","preventDefault","focusableElements","querySelectorAll","firstElement","lastElement","length","shiftKey","addEventListener","removeEventListener","primaryButton","Button","variant","onClick","handlePrimaryClick","secondaryButton","ref","role","tabIndex","Card","elevation","CardMedia","src","alt","CardHeader","isBorderless","Flex","justify","align","id","label","closeSmall","viewBox","iconSize","CardBody","dangerouslySetInnerHTML","sanitizeHTML","CardFooter","gap","ACTION_TYPES","normalizeError","error","code","isApiError","updatePmPromotions","data","SET_PM_PROMOTIONS","updateErrorForPmPromotions","SET_ERROR_FOR_PM_PROMOTIONS","activatePmPromotion","identifier","path","NAMESPACE","apiFetch","method","controls","dispatch","STORE_NAME","e","dismissPmPromotion","usePmPromotions","useSelect","select","getPmPromotions","getPmPromotionsError","isResolving","pmPromotions","pmPromotionsError","isLoading","usePmPromotionActions","useDispatch","defaultState","undefined","receivePmPromotions","state","action","isPmPromotion","value","obj","promo_id","payment_method","payment_method_title","title","cta_label","tc_url","tc_label","result","Array","isArray","every","Error","PM_PROMOTIONS_STORE_NAME","store","createReduxStore","reducer","combineReducers","actions","selectors","resolvers","register","getPageSource","window","location","pathname","search","SpotlightPromotion","spotlightPromotion","useMemo","find","promo","getEventProperties","display_context","source","handleView","recordEvent","handleSecondaryClick","link_type","parsedUrl","URL","protocol","open","handleDismiss","badge_text","badge_type"],"sourceRoot":""}