@bikdotai/bik-component-library 0.0.807-beta.0 → 0.0.807-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"FeatureAnnouncementProvider.js","sources":["../../../../src/components/feature-announcements/FeatureAnnouncementProvider.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useState } from 'react';\nimport Joyride, { ACTIONS } from 'react-joyride';\nimport { SELECTORS } from './constants';\nimport { useFeatureAnnouncements } from './hooks';\nimport MajorUpdatePopup from './MajorUpdatePopup';\nimport MinorUpdatePopup from './MinorUpdatePopup';\nimport { FeatureAnnouncement, FeatureAnnouncementProviderProps } from './types';\nimport { VideoModal } from './VideoModal';\n\nconst FeatureAnnouncementProvider: React.FC<\n\tFeatureAnnouncementProviderProps\n> = ({\n\tchildren,\n\tfetchVisibleFeatures,\n\tgetStoreFeatureProgress,\n\tfetchFeatureById,\n\tmarkFeatureAsViewedForStore,\n\tisFeatureApplicableToCurrentPage,\n\tmodule,\n\trouter,\n\tstoreId,\n\tonAnnouncementShown,\n\tonAnnouncementInteracted,\n}) => {\n\tconst {\n\t\tmajorUpdateFeatures,\n\t\tminorUpdateFeatures,\n\t\tisLoading,\n\t\tmarkFeatureAsViewed,\n\t} = useFeatureAnnouncements({\n\t\tfetchVisibleFeatures,\n\t\tgetStoreFeatureProgress,\n\t\tfetchFeatureById,\n\t\tmarkFeatureAsViewedForStore,\n\t\tisFeatureApplicableToCurrentPage,\n\t\tmodule,\n\t\trouter,\n\t});\n\n\tconst [currentMajorFeature, setCurrentMajorFeature] =\n\t\tuseState<FeatureAnnouncement | null>(null);\n\tconst [currentMinorFeature, setCurrentMinorFeature] =\n\t\tuseState<FeatureAnnouncement | null>(null);\n\tconst [runJoyride, setRunJoyride] = useState(false);\n\tconst [joyrideSteps, setJoyrideSteps] = useState<any[]>([]);\n\tconst [runMajorJoyride, setRunMajorJoyride] = useState(false);\n\tconst [majorJoyrideSteps, setMajorJoyrideSteps] = useState<any[]>([]);\n\tconst [isProcessingMajorUpdate, setIsProcessingMajorUpdate] = useState(false);\n\tconst [isProcessingMinorUpdate, setIsProcessingMinorUpdate] = useState(false);\n\tconst [availableMinorFeatures, setAvailableMinorFeatures] = useState<\n\t\tFeatureAnnouncement[]\n\t>([]);\n\tconst [minorFeaturesSkipped, setMinorFeaturesSkipped] = useState(false);\n\tconst [showMinorUpdates, setShowMinorUpdates] = useState(false);\n\tconst [isVideoModalOpen, setIsVideoModalOpen] = useState(false);\n\tconst [videoUrl, setVideoUrl] = useState('');\n\tconst [blockPopups, setBlockPopups] = useState(false);\n\tconst [isClosingMajor, setIsClosingMajor] = useState(false);\n\tconst [isClosingMinor, setIsClosingMinor] = useState(false);\n\tconst [majorJoyrideKey, setMajorJoyrideKey] = useState(0);\n\tconst [minorJoyrideKey, setMinorJoyrideKey] = useState(0);\n\tconst [shownMinorFeatureIds, setShownMinorFeatureIds] = useState<Set<string>>(\n\t\tnew Set(),\n\t);\n\n\t// Add custom style for spotlight cutout effect\n\tuseEffect(() => {\n\t\tconst styleId = 'minor-spotlight-cutout-style';\n\t\tlet styleElement = document.getElementById(styleId) as HTMLStyleElement;\n\n\t\tif (!styleElement) {\n\t\t\tstyleElement = document.createElement('style');\n\t\t\tstyleElement.id = styleId;\n\t\t\tdocument.head.appendChild(styleElement);\n\t\t}\n\n\t\tstyleElement.textContent = `\n\t\t\t.react-joyride__spotlight {\n\t\t\t\ttransition: box-shadow 0.3s ease-in-out !important;\n\t\t\t\twill-change: box-shadow, transform;\n\t\t\t\ttransform: translateZ(0);\n\t\t\t}\n\t\t\t.react-joyride__tooltip {\n\t\t\t\twill-change: transform, opacity;\n\t\t\t\ttransform: translateZ(0);\n\t\t\t}\n\t\t\t.react-joyride__floater {\n\t\t\t\tright: 12px !important;\n\t\t\t\tleft: auto !important;\n\t\t\t}\n\t\t`;\n\n\t\treturn () => {\n\t\t\tconst el = document.getElementById(styleId);\n\t\t\tif (el) {\n\t\t\t\tel.remove();\n\t\t\t}\n\t\t};\n\t}, []);\n\n\t// Force Joyride remount on navigation to prevent stale state\n\tuseEffect(() => {\n\t\tsetMajorJoyrideKey((prev) => prev + 1);\n\t\tsetMinorJoyrideKey((prev) => prev + 1);\n\t\tsetIsClosingMajor(false);\n\t\tsetIsClosingMinor(false);\n\t\t// Reset session tracking on navigation to allow features to show on new pages\n\t\tsetShownMinorFeatureIds(new Set());\n\t}, [router?.pathname]);\n\n\tuseEffect(() => {\n\t\tif (\n\t\t\tmajorUpdateFeatures.length > 0 &&\n\t\t\t!currentMajorFeature &&\n\t\t\t!isLoading &&\n\t\t\t!isProcessingMajorUpdate &&\n\t\t\t!blockPopups\n\t\t) {\n\t\t\tsetShowMinorUpdates(false);\n\t\t\tsetMinorFeaturesSkipped(false);\n\t\t\tsetRunJoyride(false);\n\t\t\tsetJoyrideSteps([]);\n\t\t\tsetCurrentMinorFeature(null);\n\t\t\tsetAvailableMinorFeatures([]);\n\n\t\t\tlet attempts = 0;\n\t\t\tconst MAX_ATTEMPTS = 10;\n\n\t\t\tconst checkWhatsNewButton = () => {\n\t\t\t\tattempts++;\n\t\t\t\tconst whatsNewButton = document.querySelector(\n\t\t\t\t\t'[data-testid=\"whats-new-button\"]',\n\t\t\t\t);\n\n\t\t\t\tif (whatsNewButton) {\n\t\t\t\t\tshowMajorUpdateJoyride(majorUpdateFeatures[0]);\n\t\t\t\t} else if (attempts < MAX_ATTEMPTS) {\n\t\t\t\t\tsetTimeout(checkWhatsNewButton, 1000);\n\t\t\t\t} else {\n\t\t\t\t\tsetShowMinorUpdates(true);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tcheckWhatsNewButton();\n\t\t} else if (majorUpdateFeatures.length === 0 && !isLoading) {\n\t\t\tsetShowMinorUpdates(true);\n\t\t}\n\t}, [\n\t\tmajorUpdateFeatures,\n\t\tcurrentMajorFeature,\n\t\tisLoading,\n\t\tisProcessingMajorUpdate,\n\t\tblockPopups,\n\t]);\n\n\tuseEffect(() => {\n\t\t// Only run this special logic if a feature is being forced via URL\n\t\tconst featureIdFromQuery = router?.query?.['featureId'] as string;\n\n\t\tif (!featureIdFromQuery || isLoading || minorUpdateFeatures.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst forcedFeature = minorUpdateFeatures.find(\n\t\t\t(f) => f.id === featureIdFromQuery,\n\t\t);\n\n\t\tif (!forcedFeature || !forcedFeature.featureTag) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Prevent the standard flow from interfering\n\t\tsetMinorFeaturesSkipped(true);\n\t\t// Mark that we're processing to prevent other effects from interfering\n\t\tsetIsProcessingMinorUpdate(true);\n\n\t\tlet attempts = 0;\n\t\tconst maxAttempts = 25; // 5 seconds\n\t\tconst interval = setInterval(() => {\n\t\t\tattempts++;\n\t\t\tconst targetSelector =\n\t\t\t\tforcedFeature.featureTag.startsWith('#') ||\n\t\t\t\tforcedFeature.featureTag.startsWith('.') ||\n\t\t\t\tforcedFeature.featureTag.startsWith('[')\n\t\t\t\t\t? forcedFeature.featureTag\n\t\t\t\t\t: `#${forcedFeature.featureTag}`;\n\n\t\t\tconst element = document.querySelector(targetSelector);\n\n\t\t\tif (element) {\n\t\t\t\t// In test mode, pass the feature array directly to avoid async state issues\n\t\t\t\tconst testModeFeatures = [forcedFeature];\n\t\t\t\tsetAvailableMinorFeatures(testModeFeatures);\n\t\t\t\tshowMinorUpdateJoyride(forcedFeature, testModeFeatures);\n\t\t\t\t// Don't reset processing flag here - let user interaction handle it\n\t\t\t\t// This prevents auto-closing when multiple popups exist or when scrolling\n\t\t\t\tclearInterval(interval);\n\t\t\t} else if (attempts >= maxAttempts) {\n\t\t\t\t// Fallback for safety, though user expects it to be there.\n\t\t\t\t// We could log an error here.\n\t\t\t\t// Only reset on timeout (element not found)\n\t\t\t\tsetIsProcessingMinorUpdate(false);\n\t\t\t\tclearInterval(interval);\n\t\t\t}\n\t\t}, 200);\n\n\t\treturn () => {\n\t\t\tclearInterval(interval);\n\t\t\t// Don't reset processing flag on cleanup - it causes premature popup closure\n\t\t\t// The flag will be managed by user interactions (skip/explore handlers)\n\t\t};\n\t}, [minorUpdateFeatures, router?.query?.['featureId'], isLoading]);\n\n\tuseEffect(() => {\n\t\tif (\n\t\t\tminorUpdateFeatures.length > 0 &&\n\t\t\t!isLoading &&\n\t\t\t!runJoyride &&\n\t\t\t!isProcessingMinorUpdate &&\n\t\t\t!currentMinorFeature &&\n\t\t\t!minorFeaturesSkipped &&\n\t\t\tshowMinorUpdates &&\n\t\t\t!blockPopups\n\t\t) {\n\t\t\tlet observer: MutationObserver | null = null;\n\t\t\tlet scrollListener: (() => void) | null = null;\n\t\t\tlet checkTimeout: ReturnType<typeof setTimeout> | null = null;\n\t\t\tlet isCleanedUp = false;\n\n\t\t\tconst checkElementsAndStartTour = () => {\n\t\t\t\tif (\n\t\t\t\t\tisCleanedUp ||\n\t\t\t\t\tisProcessingMinorUpdate ||\n\t\t\t\t\tcurrentMinorFeature ||\n\t\t\t\t\tminorFeaturesSkipped ||\n\t\t\t\t\t!showMinorUpdates\n\t\t\t\t)\n\t\t\t\t\treturn;\n\n\t\t\t\tconst availableFeatures = minorUpdateFeatures.filter((feature) => {\n\t\t\t\t\tif (!feature.featureTag || feature.featureTag.trim() === '') {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Skip features already shown in this session\n\t\t\t\t\tif (shownMinorFeatureIds.has(feature.id)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst targetSelector =\n\t\t\t\t\t\tfeature.featureTag.startsWith('#') ||\n\t\t\t\t\t\tfeature.featureTag.startsWith('.') ||\n\t\t\t\t\t\tfeature.featureTag.startsWith('[')\n\t\t\t\t\t\t\t? feature.featureTag\n\t\t\t\t\t\t\t: `#${feature.featureTag}`;\n\n\t\t\t\t\tconst element = document.querySelector(targetSelector);\n\t\t\t\t\treturn element !== null;\n\t\t\t\t});\n\n\t\t\t\tif (availableFeatures.length > 0) {\n\t\t\t\t\tsetAvailableMinorFeatures(availableFeatures);\n\t\t\t\t\t// Pass features directly to avoid async state issues\n\t\t\t\t\tshowMinorUpdateJoyride(availableFeatures[0], availableFeatures);\n\n\t\t\t\t\tif (observer) {\n\t\t\t\t\t\tobserver.disconnect();\n\t\t\t\t\t\tobserver = null;\n\t\t\t\t\t}\n\t\t\t\t\tif (scrollListener) {\n\t\t\t\t\t\twindow.removeEventListener('scroll', scrollListener);\n\t\t\t\t\t\tscrollListener = null;\n\t\t\t\t\t}\n\t\t\t\t\tif (checkTimeout) {\n\t\t\t\t\t\tclearTimeout(checkTimeout);\n\t\t\t\t\t\tcheckTimeout = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tobserver = new MutationObserver((mutations) => {\n\t\t\t\tlet shouldCheck = false;\n\t\t\t\tfor (const mutation of mutations) {\n\t\t\t\t\tif (mutation.type === 'childList' && mutation.addedNodes.length > 0) {\n\t\t\t\t\t\tfor (let i = 0; i < mutation.addedNodes.length; i++) {\n\t\t\t\t\t\t\tconst node = mutation.addedNodes[i];\n\t\t\t\t\t\t\tif (node.nodeType === Node.ELEMENT_NODE) {\n\t\t\t\t\t\t\t\tconst element = node as Element;\n\t\t\t\t\t\t\t\tif (element.id || element.querySelector('[id]')) {\n\t\t\t\t\t\t\t\t\tshouldCheck = true;\n\t\t\t\t\t\t\t\t\tbreak;\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}\n\t\t\t\t\tif (shouldCheck) break;\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\t!runJoyride &&\n\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\tshowMinorUpdates &&\n\t\t\t\t\tshouldCheck\n\t\t\t\t) {\n\t\t\t\t\tif (checkTimeout) {\n\t\t\t\t\t\tclearTimeout(checkTimeout);\n\t\t\t\t\t}\n\t\t\t\t\tcheckTimeout = setTimeout(() => {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\t\t\tshowMinorUpdates\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tcheckElementsAndStartTour();\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 200);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tscrollListener = () => {\n\t\t\t\tif (\n\t\t\t\t\t!runJoyride &&\n\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\tshowMinorUpdates\n\t\t\t\t) {\n\t\t\t\t\tif (checkTimeout) {\n\t\t\t\t\t\tclearTimeout(checkTimeout);\n\t\t\t\t\t}\n\t\t\t\t\t// Use RAF for smoother performance synced with browser paint\n\t\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\t\tcheckTimeout = setTimeout(() => {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\t\t\t\tshowMinorUpdates\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tcheckElementsAndStartTour();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, 300);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif (observer) {\n\t\t\t\tobserver.observe(document.body, {\n\t\t\t\t\tchildList: true,\n\t\t\t\t\tsubtree: true,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (scrollListener) {\n\t\t\t\twindow.addEventListener('scroll', scrollListener, { passive: true });\n\t\t\t}\n\n\t\t\tcheckElementsAndStartTour();\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (\n\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\tshowMinorUpdates\n\t\t\t\t) {\n\t\t\t\t\tcheckElementsAndStartTour();\n\t\t\t\t}\n\t\t\t}, 100);\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (\n\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\tshowMinorUpdates\n\t\t\t\t) {\n\t\t\t\t\tcheckElementsAndStartTour();\n\t\t\t\t}\n\t\t\t}, 1000);\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (\n\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\tshowMinorUpdates\n\t\t\t\t) {\n\t\t\t\t\tcheckElementsAndStartTour();\n\t\t\t\t}\n\t\t\t}, 500);\n\n\t\t\treturn () => {\n\t\t\t\tisCleanedUp = true;\n\t\t\t\tif (observer) {\n\t\t\t\t\tobserver.disconnect();\n\t\t\t\t}\n\t\t\t\tif (scrollListener) {\n\t\t\t\t\twindow.removeEventListener('scroll', scrollListener);\n\t\t\t\t}\n\t\t\t\tif (checkTimeout) {\n\t\t\t\t\tclearTimeout(checkTimeout);\n\t\t\t\t}\n\t\t\t};\n\t\t} else if (minorUpdateFeatures.length === 0 || isLoading) {\n\t\t\t// Don't clear joyride if we're in test mode with an active feature\n\t\t\tconst featureIdFromQuery = router?.query?.['featureId'] as string;\n\t\t\tconst isTestModeWithActiveFeature =\n\t\t\t\tfeatureIdFromQuery && currentMinorFeature;\n\n\t\t\tif (!isTestModeWithActiveFeature) {\n\t\t\t\tsetRunJoyride(false);\n\t\t\t\tsetJoyrideSteps([]);\n\t\t\t\tsetCurrentMinorFeature(null);\n\t\t\t\tsetAvailableMinorFeatures([]);\n\t\t\t\tsetMinorFeaturesSkipped(false);\n\t\t\t}\n\t\t}\n\t}, [\n\t\tminorUpdateFeatures,\n\t\tisLoading,\n\t\trunJoyride,\n\t\tisProcessingMinorUpdate,\n\t\tcurrentMinorFeature,\n\t\tminorFeaturesSkipped,\n\t\tshowMinorUpdates,\n\t\tmarkFeatureAsViewed,\n\t\tblockPopups,\n\t]);\n\n\tconst showMajorUpdateJoyride = (feature) => {\n\t\tsetCurrentMajorFeature(feature);\n\n\t\tconst currentIndex = majorUpdateFeatures.findIndex(\n\t\t\t(f) => f.id === feature.id,\n\t\t);\n\t\tconst totalFeatures = majorUpdateFeatures.length;\n\n\t\tconst majorSteps = [\n\t\t\t{\n\t\t\t\ttarget: SELECTORS.WHATS_NEW_BUTTON,\n\t\t\t\tcontent: (\n\t\t\t\t\t<MajorUpdatePopup\n\t\t\t\t\t\tfeature={feature}\n\t\t\t\t\t\tcurrentIndex={currentIndex}\n\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\tonSkip={() => handleSkipMajorUpdate(feature)}\n\t\t\t\t\t\tonExplore={(triggeredAction) => handleExploreFeature(feature, triggeredAction)}\n\t\t\t\t\t\tonPrevious={() => handlePreviousMajorUpdate(feature)}\n\t\t\t\t\t\tonNext={() => handleNextMajorUpdate(feature)}\n\t\t\t\t\t\tsetIsClosing={setIsClosingMajor}\n\t\t\t\t\t/>\n\t\t\t\t),\n\t\t\t\tplacement: 'bottom-start',\n\t\t\t\tplacementBeacon: 'top-end',\n\t\t\t\tdisableBeacon: true,\n\t\t\t\thideCloseButton: true,\n\t\t\t\thideSkipButton: true,\n\t\t\t\thideFooter: true,\n\t\t\t\toffset: 0,\n\t\t\t\tdata: { feature, isMajor: true },\n\t\t\t\tstyles: {\n\t\t\t\t\ttooltip: {\n\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\tborderRadius: '16px',\n\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t},\n\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t},\n\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\n\t\tsetMajorJoyrideSteps(majorSteps);\n\t\tsetRunMajorJoyride(true);\n\n\t\t// Fire announcement shown callback\n\t\tif (onAnnouncementShown && storeId) {\n\t\t\tonAnnouncementShown({\n\t\t\t\tstoreId,\n\t\t\t\tannouncementId: feature.id,\n\t\t\t\tannouncementTitle: feature.title,\n\t\t\t\timageUrl: feature.displayImage || feature.image,\n\t\t\t\tvideoUrl: feature.productVideo,\n\t\t\t});\n\t\t}\n\t};\n\n\tconst handleSkipMajorUpdate = useCallback(\n\t\tasync (feature) => {\n\t\t\tconst targetFeature = feature || currentMajorFeature;\n\n\t\t\tif (targetFeature) {\n\t\t\t\tsetIsProcessingMajorUpdate(true);\n\n\t\t\t\tawait Promise.all(\n\t\t\t\t\tmajorUpdateFeatures.map((majorFeature) =>\n\t\t\t\t\t\tmarkFeatureAsViewed(majorFeature.id),\n\t\t\t\t\t),\n\t\t\t\t);\n\n\t\t\t\tsetRunMajorJoyride(false);\n\t\t\t\tsetCurrentMajorFeature(null);\n\t\t\t\tsetMajorJoyrideSteps([]);\n\n\t\t\t\tsetShowMinorUpdates(true);\n\n\t\t\t\t// Fire announcement interacted callback for Skip\n\t\t\t\tif (onAnnouncementInteracted && storeId) {\n\t\t\t\t\tonAnnouncementInteracted({\n\t\t\t\t\t\tstoreId,\n\t\t\t\t\t\tannouncementId: targetFeature.id,\n\t\t\t\t\t\tannouncementTitle: targetFeature.title,\n\t\t\t\t\t\timageUrl: targetFeature.displayImage || targetFeature.image,\n\t\t\t\t\t\tvideoUrl: targetFeature.productVideo,\n\t\t\t\t\t\tbuttonClicked: 'Skip',\n\t\t\t\t\t\tbuttonName: 'Skip',\n\t\t\t\t\t\tbuttonUrl: undefined,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsetIsProcessingMajorUpdate(false);\n\t\t\t\t}, 500);\n\t\t\t} else {\n\t\t\t}\n\t\t},\n\t\t[currentMajorFeature, majorUpdateFeatures, markFeatureAsViewed],\n\t);\n\n\tconst handleExploreFeature = useCallback(\n\t\tasync (feature, triggeredAction?: string) => {\n\t\t\tsetIsProcessingMajorUpdate(true);\n\t\t\t// Await so the feature is marked before any page navigation\n\t\t\tawait markFeatureAsViewed(feature.id);\n\t\t\tconst action = triggeredAction ?? feature.primaryButton?.action;\n\t\t\tif (action === 'Play Video' && feature.productVideo) {\n\t\t\t\tsetVideoUrl(feature.productVideo);\n\t\t\t\tsetIsVideoModalOpen(true);\n\t\t\t\tsetBlockPopups(true);\n\t\t\t}\n\n\t\t\tif (action === 'Open link') {\n\t\t\t\tconst url = feature.primaryButton?.redirectionUrl || feature.redirectUrl;\n\t\t\t\tif (url && !url.startsWith('http')) {\n\t\t\t\t\twindow.location.href = url;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsetRunMajorJoyride(false);\n\t\t\tsetCurrentMajorFeature(null);\n\t\t\tsetMajorJoyrideSteps([]);\n\t\t\tconst currentIndex = majorUpdateFeatures.findIndex(\n\t\t\t\t(f) => f.id === feature.id,\n\t\t\t);\n\t\t\tconst isLastMajorUpdate = currentIndex === majorUpdateFeatures.length - 1;\n\t\t\tif (isLastMajorUpdate) {\n\t\t\t\tsetShowMinorUpdates(true);\n\t\t\t}\n\n\t\t\t// Fire announcement interacted callback for Primary button\n\t\t\tif (onAnnouncementInteracted && storeId) {\n\t\t\t\tonAnnouncementInteracted({\n\t\t\t\t\tstoreId,\n\t\t\t\t\tannouncementId: feature.id,\n\t\t\t\t\tannouncementTitle: feature.title,\n\t\t\t\t\timageUrl: feature.displayImage || feature.image,\n\t\t\t\t\tvideoUrl: feature.productVideo,\n\t\t\t\t\tbuttonClicked: 'Primary',\n\t\t\t\t\tbuttonName: feature.buttonText || 'Explore',\n\t\t\t\t\tbuttonUrl: feature.redirectUrl || feature.productVideo,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tsetIsProcessingMajorUpdate(false);\n\t\t\t}, 500);\n\t\t},\n\t\t[majorUpdateFeatures, markFeatureAsViewed],\n\t);\n\n\tconst handlePreviousMajorUpdate = useCallback(\n\t\t(feature) => {\n\t\t\tconst targetFeature = feature || currentMajorFeature;\n\n\t\t\tif (!targetFeature) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst currentIndex = majorUpdateFeatures.findIndex(\n\t\t\t\t(f) => f.id === targetFeature.id,\n\t\t\t);\n\n\t\t\tif (currentIndex > 0) {\n\t\t\t\tconst prevFeature = majorUpdateFeatures[currentIndex - 1];\n\t\t\t\tsetCurrentMajorFeature(prevFeature);\n\n\t\t\t\tconst prevIndex = currentIndex - 1;\n\t\t\t\tconst totalFeatures = majorUpdateFeatures.length;\n\n\t\t\t\tconst updatedSteps = [\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget: '[data-testid=\"whats-new-button\"]',\n\t\t\t\t\t\tcontent: (\n\t\t\t\t\t\t\t<MajorUpdatePopup\n\t\t\t\t\t\t\t\tfeature={prevFeature}\n\t\t\t\t\t\t\t\tcurrentIndex={prevIndex}\n\t\t\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\t\t\tonSkip={() => handleSkipMajorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tonExplore={(triggeredAction) => handleExploreFeature(prevFeature, triggeredAction)}\n\t\t\t\t\t\t\t\tonPrevious={() => handlePreviousMajorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tonNext={() => handleNextMajorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tsetIsClosing={setIsClosingMajor}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t\tplacement: 'bottom-start',\n\t\t\t\t\t\tplacementBeacon: 'top-end',\n\t\t\t\t\t\tdisableBeacon: true,\n\t\t\t\t\t\thideCloseButton: true,\n\t\t\t\t\t\thideSkipButton: true,\n\t\t\t\t\t\thideFooter: true,\n\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\tdata: { feature: prevFeature, isMajor: true },\n\t\t\t\t\t\tstyles: {\n\t\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\tborderRadius: '16px',\n\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t];\n\n\t\t\t\tsetMajorJoyrideSteps(updatedSteps);\n\t\t\t} else {\n\t\t\t}\n\t\t},\n\t\t[currentMajorFeature, majorUpdateFeatures],\n\t);\n\n\tconst handleNextMajorUpdate = useCallback(\n\t\t(feature) => {\n\t\t\tconst targetFeature = feature || currentMajorFeature;\n\n\t\t\tif (!targetFeature) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst currentIndex = majorUpdateFeatures.findIndex(\n\t\t\t\t(f) => f.id === targetFeature.id,\n\t\t\t);\n\n\t\t\tif (currentIndex < majorUpdateFeatures.length - 1) {\n\t\t\t\tconst nextFeature = majorUpdateFeatures[currentIndex + 1];\n\t\t\t\tsetCurrentMajorFeature(nextFeature);\n\n\t\t\t\tconst nextIndex = currentIndex + 1;\n\t\t\t\tconst totalFeatures = majorUpdateFeatures.length;\n\n\t\t\t\tconst updatedSteps = [\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget: '[data-testid=\"whats-new-button\"]',\n\t\t\t\t\t\tcontent: (\n\t\t\t\t\t\t\t<MajorUpdatePopup\n\t\t\t\t\t\t\t\tfeature={nextFeature}\n\t\t\t\t\t\t\t\tcurrentIndex={nextIndex}\n\t\t\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\t\t\tonSkip={() => handleSkipMajorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tonExplore={(triggeredAction) => handleExploreFeature(nextFeature, triggeredAction)}\n\t\t\t\t\t\t\t\tonPrevious={() => handlePreviousMajorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tonNext={() => handleNextMajorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tsetIsClosing={setIsClosingMajor}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t\tplacement: 'bottom-start',\n\t\t\t\t\t\tplacementBeacon: 'top-end',\n\t\t\t\t\t\tdisableBeacon: true,\n\t\t\t\t\t\thideCloseButton: true,\n\t\t\t\t\t\thideSkipButton: true,\n\t\t\t\t\t\thideFooter: true,\n\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\tdata: { feature: nextFeature, isMajor: true },\n\t\t\t\t\t\tstyles: {\n\t\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\tborderRadius: '16px',\n\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t];\n\n\t\t\t\tsetMajorJoyrideSteps(updatedSteps);\n\t\t\t} else {\n\t\t\t\tsetIsProcessingMajorUpdate(true);\n\n\t\t\t\tmarkFeatureAsViewed(targetFeature.id);\n\t\t\t\tsetRunMajorJoyride(false);\n\t\t\t\tsetCurrentMajorFeature(null);\n\t\t\t\tsetMajorJoyrideSteps([]);\n\n\t\t\t\tsetShowMinorUpdates(true);\n\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsetIsProcessingMajorUpdate(false);\n\t\t\t\t}, 500);\n\t\t\t}\n\t\t},\n\t\t[currentMajorFeature, majorUpdateFeatures, markFeatureAsViewed],\n\t);\n\n\tconst showMajorUpdatePopup = () => {\n\t\tif (majorUpdateFeatures.length > 0 && !currentMajorFeature) {\n\t\t\tconst whatsNewButton = document.querySelector(\n\t\t\t\t'[data-testid=\"whats-new-button\"]',\n\t\t\t);\n\n\t\t\tif (whatsNewButton) {\n\t\t\t\tshowMajorUpdateJoyride(majorUpdateFeatures[0]);\n\t\t\t}\n\t\t}\n\t};\n\n\tuseEffect(() => {\n\t\t(window as any).showMajorUpdatePopup = showMajorUpdatePopup;\n\t\treturn () => {\n\t\t\tdelete (window as any).showMajorUpdatePopup;\n\t\t};\n\t}, [majorUpdateFeatures, currentMajorFeature]);\n\tconst handleMajorJoyrideCallback = useCallback(\n\t\t(data) => {\n\t\t\tconst { action } = data;\n\n\t\t\tif (action === ACTIONS.CLOSE) {\n\t\t\t\tif (currentMajorFeature) {\n\t\t\t\t\tsetIsProcessingMajorUpdate(true);\n\n\t\t\t\t\tmajorUpdateFeatures.forEach((majorFeature) => {\n\t\t\t\t\t\tmarkFeatureAsViewed(majorFeature.id);\n\t\t\t\t\t});\n\n\t\t\t\t\tsetShowMinorUpdates(true);\n\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tsetIsProcessingMajorUpdate(false);\n\t\t\t\t\t}, 500);\n\t\t\t\t}\n\n\t\t\t\tsetRunMajorJoyride(false);\n\t\t\t\tsetCurrentMajorFeature(null);\n\t\t\t\tsetMajorJoyrideSteps([]);\n\t\t\t}\n\t\t},\n\t\t[currentMajorFeature, majorUpdateFeatures, markFeatureAsViewed],\n\t);\n\n\tconst handleMinorJoyrideCallback = useCallback(\n\t\t(data) => {\n\t\t\tconst { action } = data;\n\n\t\t\tif (action === ACTIONS.CLOSE) {\n\t\t\t\tif (currentMinorFeature) {\n\t\t\t\t\tsetIsProcessingMinorUpdate(true);\n\n\t\t\t\t\t// Only mark the current feature as viewed, not all features\n\t\t\t\t\tmarkFeatureAsViewed(currentMinorFeature.id);\n\n\t\t\t\t\t// Check if there are more features to show\n\t\t\t\t\tconst currentIndex = availableMinorFeatures.findIndex(\n\t\t\t\t\t\t(f) => f.id === currentMinorFeature.id,\n\t\t\t\t\t);\n\t\t\t\t\tconst isLastFeature =\n\t\t\t\t\t\tcurrentIndex === availableMinorFeatures.length - 1;\n\n\t\t\t\t\tif (isLastFeature) {\n\t\t\t\t\t\t// Only skip remaining features if this was the last one\n\t\t\t\t\t\tsetMinorFeaturesSkipped(true);\n\t\t\t\t\t}\n\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tsetIsProcessingMinorUpdate(false);\n\t\t\t\t\t}, 500);\n\t\t\t\t}\n\n\t\t\t\tsetRunJoyride(false);\n\t\t\t\tsetCurrentMinorFeature(null);\n\t\t\t\tsetJoyrideSteps([]);\n\t\t\t}\n\t\t},\n\t\t[currentMinorFeature, availableMinorFeatures, markFeatureAsViewed],\n\t);\n\tconst showMinorUpdateJoyride = async (feature, featuresToUse?) => {\n\t\tsetCurrentMinorFeature(feature);\n\n\t\t// Use provided features array or fall back to state (for test mode)\n\t\tconst features = featuresToUse || availableMinorFeatures;\n\t\tconst currentIndex = features.findIndex((f) => f.id === feature.id);\n\t\tconst totalFeatures = features.length;\n\n\t\tconst targetSelector =\n\t\t\tfeature.featureTag.startsWith('#') ||\n\t\t\tfeature.featureTag.startsWith('.') ||\n\t\t\tfeature.featureTag.startsWith('[')\n\t\t\t\t? feature.featureTag\n\t\t\t\t: `#${feature.featureTag}`;\n\n\t\t// Scroll to target element smoothly before showing popup\n\t\tconst targetElement = document.querySelector(targetSelector);\n\t\tif (targetElement) {\n\t\t\ttry {\n\t\t\t\t// Dynamically import to avoid circular dependencies\n\t\t\t\tconst { scrollToElementSmooth } = await import(\n\t\t\t\t\t'./utils/elementHelpers'\n\t\t\t\t);\n\t\t\t\tawait scrollToElementSmooth(targetElement, 120);\n\t\t\t} catch (error) {\n\t\t\t\t// Scroll failed silently\n\t\t\t}\n\t\t}\n\n\t\tconst minorSteps = [\n\t\t\t{\n\t\t\t\ttarget: targetSelector,\n\t\t\t\tcontent: (\n\t\t\t\t\t<MinorUpdatePopup\n\t\t\t\t\t\tfeature={feature}\n\t\t\t\t\t\tcurrentIndex={currentIndex}\n\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\tonSkip={() => handleSkipMinorUpdate(feature)}\n\t\t\t\t\t\tonExplore={(triggeredAction) => handleExploreMinorFeature(feature, triggeredAction)}\n\t\t\t\t\t\tonPrevious={() => handlePreviousMinorUpdate(feature)}\n\t\t\t\t\t\tonNext={() => handleNextMinorUpdate(feature)}\n\t\t\t\t\t\tsetIsClosing={setIsClosingMinor}\n\t\t\t\t\t/>\n\t\t\t\t),\n\t\t\t\tplacement: 'bottom',\n\t\t\t\tplacementBeacon: 'bottom-end',\n\t\t\t\tdisableBeacon: true,\n\t\t\t\thideCloseButton: true,\n\t\t\t\thideSkipButton: true,\n\t\t\t\thideFooter: true,\n\t\t\t\toffset: 0,\n\t\t\t\tdata: { feature, isMinor: true },\n\t\t\t\tstyles: {\n\t\t\t\t\ttooltip: {\n\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t},\n\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t},\n\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\t\tsetJoyrideSteps(minorSteps);\n\t\tsetRunJoyride(true);\n\t};\n\n\tconst handleSkipMinorUpdate = useCallback(\n\t\tasync (feature) => {\n\t\t\tconst targetFeature = feature || currentMinorFeature;\n\n\t\t\tif (targetFeature) {\n\t\t\t\tsetIsProcessingMinorUpdate(true);\n\n\t\t\t\t// Only mark the current feature as viewed, not all features\n\t\t\t\tawait markFeatureAsViewed(targetFeature.id);\n\n\t\t\t\t// Add to session tracker to prevent re-showing\n\t\t\t\tsetShownMinorFeatureIds((prev) => new Set(prev).add(targetFeature.id));\n\n\t\t\t\tsetRunJoyride(false);\n\t\t\t\tsetCurrentMinorFeature(null);\n\t\t\t\tsetJoyrideSteps([]);\n\n\t\t\t\t// Find next unshown feature\n\t\t\t\tconst nextFeature = availableMinorFeatures.find(\n\t\t\t\t\t(f) => f.id !== targetFeature.id && !shownMinorFeatureIds.has(f.id),\n\t\t\t\t);\n\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsetIsProcessingMinorUpdate(false);\n\n\t\t\t\t\tif (nextFeature) {\n\t\t\t\t\t\t// Auto-advance to next feature\n\t\t\t\t\t\tshowMinorUpdateJoyride(nextFeature, availableMinorFeatures);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// No more features to show\n\t\t\t\t\t\tsetMinorFeaturesSkipped(true);\n\t\t\t\t\t}\n\t\t\t\t}, 500);\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\tcurrentMinorFeature,\n\t\t\tavailableMinorFeatures,\n\t\t\tmarkFeatureAsViewed,\n\t\t\tshownMinorFeatureIds,\n\t\t],\n\t);\n\n\tconst handleExploreMinorFeature = useCallback(\n\t\tasync (feature, triggeredAction?: string) => {\n\t\t\tsetIsProcessingMinorUpdate(true);\n\n\t\t\t// Only mark the current feature as viewed\n\t\t\t// Await so the feature is marked before any page navigation\n\t\t\tawait markFeatureAsViewed(feature.id);\n\n\t\t\t// Add to session tracker to prevent re-showing\n\t\t\tsetShownMinorFeatureIds((prev) => new Set(prev).add(feature.id));\n\n\t\t\tconst action = triggeredAction ?? feature.primaryButton?.action;\n\n\t\t\tif (action === 'Play Video' && feature.productVideo) {\n\t\t\t\tsetVideoUrl(feature.productVideo);\n\t\t\t\tsetIsVideoModalOpen(true);\n\t\t\t\tsetBlockPopups(true);\n\t\t\t}\n\n\t\t\tif (action === 'Open link') {\n\t\t\t\tconst url = feature.primaryButton?.redirectionUrl || feature.redirectUrl;\n\t\t\t\tif (url && !url.startsWith('http')) {\n\t\t\t\t\twindow.location.href = url;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsetRunJoyride(false);\n\t\t\tsetCurrentMinorFeature(null);\n\t\t\tsetJoyrideSteps([]);\n\n\t\t\t// Find next unshown feature (only auto-advance if no video modal)\n\t\t\tconst nextFeature = availableMinorFeatures.find(\n\t\t\t\t(f) => f.id !== feature.id && !shownMinorFeatureIds.has(f.id),\n\t\t\t);\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tsetIsProcessingMinorUpdate(false);\n\n\t\t\t\t// Only auto-advance if no video modal is opened\n\t\t\t\tif (nextFeature && action !== 'Play Video') {\n\t\t\t\t\t// Auto-advance to next feature\n\t\t\t\t\tshowMinorUpdateJoyride(nextFeature, availableMinorFeatures);\n\t\t\t\t} else if (!nextFeature) {\n\t\t\t\t\t// No more features to show\n\t\t\t\t\tsetMinorFeaturesSkipped(true);\n\t\t\t\t}\n\t\t\t\t// If video modal opened, wait for user to close it before advancing\n\t\t\t}, 500);\n\t\t},\n\t\t[availableMinorFeatures, markFeatureAsViewed, shownMinorFeatureIds],\n\t);\n\n\tconst handlePreviousMinorUpdate = useCallback(\n\t\tasync (feature) => {\n\t\t\tconst targetFeature = feature || currentMinorFeature;\n\n\t\t\tif (!targetFeature) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst currentIndex = availableMinorFeatures.findIndex(\n\t\t\t\t(f) => f.id === targetFeature.id,\n\t\t\t);\n\n\t\t\tif (currentIndex > 0) {\n\t\t\t\tconst prevFeature = availableMinorFeatures[currentIndex - 1];\n\t\t\t\tsetCurrentMinorFeature(prevFeature);\n\n\t\t\t\tconst targetSelector =\n\t\t\t\t\tprevFeature.featureTag.startsWith('#') ||\n\t\t\t\t\tprevFeature.featureTag.startsWith('.') ||\n\t\t\t\t\tprevFeature.featureTag.startsWith('[')\n\t\t\t\t\t\t? prevFeature.featureTag\n\t\t\t\t\t\t: `#${prevFeature.featureTag}`;\n\n\t\t\t\t// Scroll to the previous feature element\n\t\t\t\tconst targetElement = document.querySelector(targetSelector);\n\t\t\t\tif (targetElement) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst { scrollToElementSmooth } = await import(\n\t\t\t\t\t\t\t'./utils/elementHelpers'\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait scrollToElementSmooth(targetElement, 120);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t// Scroll failed silently\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst prevIndex = currentIndex - 1;\n\t\t\t\tconst totalFeatures = availableMinorFeatures.length;\n\n\t\t\t\tconst updatedSteps = [\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget: targetSelector,\n\t\t\t\t\t\tcontent: (\n\t\t\t\t\t\t\t<MinorUpdatePopup\n\t\t\t\t\t\t\t\tfeature={prevFeature}\n\t\t\t\t\t\t\t\tcurrentIndex={prevIndex}\n\t\t\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\t\t\tonSkip={() => handleSkipMinorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tonExplore={(triggeredAction) => handleExploreMinorFeature(prevFeature, triggeredAction)}\n\t\t\t\t\t\t\t\tonPrevious={() => handlePreviousMinorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tonNext={() => handleNextMinorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tsetIsClosing={setIsClosingMinor}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t\tplacement: 'bottom',\n\t\t\t\t\t\tplacementBeacon: 'bottom-end',\n\t\t\t\t\t\tdisableBeacon: true,\n\t\t\t\t\t\thideCloseButton: true,\n\t\t\t\t\t\thideSkipButton: true,\n\t\t\t\t\t\thideFooter: true,\n\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\tdata: { feature: prevFeature, isMinor: true },\n\t\t\t\t\t\tstyles: {\n\t\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t];\n\n\t\t\t\tsetJoyrideSteps(updatedSteps);\n\t\t\t}\n\t\t},\n\t\t[currentMinorFeature, availableMinorFeatures],\n\t);\n\n\tconst handleNextMinorUpdate = useCallback(\n\t\tasync (feature) => {\n\t\t\tconst targetFeature = feature || currentMinorFeature;\n\n\t\t\tif (!targetFeature) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst currentIndex = availableMinorFeatures.findIndex(\n\t\t\t\t(f) => f.id === targetFeature.id,\n\t\t\t);\n\n\t\t\tif (currentIndex < availableMinorFeatures.length - 1) {\n\t\t\t\tconst nextFeature = availableMinorFeatures[currentIndex + 1];\n\t\t\t\tsetCurrentMinorFeature(nextFeature);\n\n\t\t\t\tconst targetSelector =\n\t\t\t\t\tnextFeature.featureTag.startsWith('#') ||\n\t\t\t\t\tnextFeature.featureTag.startsWith('.') ||\n\t\t\t\t\tnextFeature.featureTag.startsWith('[')\n\t\t\t\t\t\t? nextFeature.featureTag\n\t\t\t\t\t\t: `#${nextFeature.featureTag}`;\n\n\t\t\t\t// Scroll to the next feature element\n\t\t\t\tconst targetElement = document.querySelector(targetSelector);\n\t\t\t\tif (targetElement) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst { scrollToElementSmooth } = await import(\n\t\t\t\t\t\t\t'./utils/elementHelpers'\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait scrollToElementSmooth(targetElement, 120);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t// Scroll failed silently\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst nextIndex = currentIndex + 1;\n\t\t\t\tconst totalFeatures = availableMinorFeatures.length;\n\n\t\t\t\tconst updatedSteps = [\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget: targetSelector,\n\t\t\t\t\t\tcontent: (\n\t\t\t\t\t\t\t<MinorUpdatePopup\n\t\t\t\t\t\t\t\tfeature={nextFeature}\n\t\t\t\t\t\t\t\tcurrentIndex={nextIndex}\n\t\t\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\t\t\tonSkip={() => handleSkipMinorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tonExplore={(triggeredAction) => handleExploreMinorFeature(nextFeature, triggeredAction)}\n\t\t\t\t\t\t\t\tonPrevious={() => handlePreviousMinorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tonNext={() => handleNextMinorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tsetIsClosing={setIsClosingMinor}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t\tplacement: 'bottom',\n\t\t\t\t\t\tplacementBeacon: 'bottom-end',\n\t\t\t\t\t\tdisableBeacon: true,\n\t\t\t\t\t\thideCloseButton: true,\n\t\t\t\t\t\thideSkipButton: true,\n\t\t\t\t\t\thideFooter: true,\n\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\tdata: { feature: nextFeature, isMinor: true },\n\t\t\t\t\t\tstyles: {\n\t\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t];\n\n\t\t\t\tsetJoyrideSteps(updatedSteps);\n\t\t\t} else {\n\t\t\t\tsetIsProcessingMinorUpdate(true);\n\t\t\t\tsetMinorFeaturesSkipped(true);\n\n\t\t\t\tmarkFeatureAsViewed(targetFeature.id);\n\t\t\t\tsetRunJoyride(false);\n\t\t\t\tsetCurrentMinorFeature(null);\n\t\t\t\tsetJoyrideSteps([]);\n\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsetIsProcessingMinorUpdate(false);\n\t\t\t\t}, 500);\n\t\t\t}\n\t\t},\n\t\t[currentMinorFeature, availableMinorFeatures, markFeatureAsViewed],\n\t);\n\n\treturn (\n\t\t<>\n\t\t\t{children}\n\n\t\t\t{majorJoyrideSteps.length > 0 && (\n\t\t\t\t<Joyride\n\t\t\t\t\tkey={`major-joyride-${majorJoyrideKey}`}\n\t\t\t\t\tsteps={majorJoyrideSteps}\n\t\t\t\t\trun={runMajorJoyride}\n\t\t\t\t\tcontinuous={false}\n\t\t\t\t\tshowProgress={false}\n\t\t\t\t\tshowSkipButton={false}\n\t\t\t\t\tcallback={handleMajorJoyrideCallback}\n\t\t\t\t\tdisableOverlayClose={false}\n\t\t\t\t\tdisableCloseOnEsc={false}\n\t\t\t\t\tdisableOverlay={false}\n\t\t\t\t\tspotlightClicks={false}\n\t\t\t\t\tstyles={{\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tprimaryColor: '#007bff',\n\t\t\t\t\t\t\tzIndex: 10000,\n\t\t\t\t\t\t\twidth: 'auto',\n\t\t\t\t\t\t\tarrowColor: isClosingMajor ? 'transparent' : '#212121',\n\t\t\t\t\t\t},\n\t\t\t\t\t\toverlay: {\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tspotlight: {\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\tborderRadius: '16px',\n\t\t\t\t\t\t\tfontSize: '14px',\n\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t}}\n\t\t\t\t\tlocale={{\n\t\t\t\t\t\tback: 'Back',\n\t\t\t\t\t\tclose: 'Close',\n\t\t\t\t\t\tlast: 'Close',\n\t\t\t\t\t\tnext: 'Next',\n\t\t\t\t\t\tskip: 'Skip',\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{joyrideSteps.length > 0 && (\n\t\t\t\t<Joyride\n\t\t\t\t\tkey={`minor-joyride-${minorJoyrideKey}`}\n\t\t\t\t\tsteps={joyrideSteps}\n\t\t\t\t\trun={runJoyride}\n\t\t\t\t\tcontinuous={false}\n\t\t\t\t\tshowProgress={false}\n\t\t\t\t\tshowSkipButton={false}\n\t\t\t\t\tcallback={handleMinorJoyrideCallback}\n\t\t\t\t\tdisableOverlayClose={false}\n\t\t\t\t\tdisableCloseOnEsc={false}\n\t\t\t\t\tdisableOverlay={false}\n\t\t\t\t\tscrollToFirstStep={true}\n\t\t\t\t\tscrollOffset={120}\n\t\t\t\t\tdisableScrolling={false}\n\t\t\t\t\tstyles={{\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tprimaryColor: '#007bff',\n\t\t\t\t\t\t\tzIndex: 10000,\n\t\t\t\t\t\t\twidth: 'auto',\n\t\t\t\t\t\t\tarrowColor: isClosingMinor ? 'transparent' : '#ffffff',\n\t\t\t\t\t\t},\n\t\t\t\t\t\toverlay: {\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tspotlight: {\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\tborderRadius: '8px',\n\t\t\t\t\t\t\tboxShadow: isClosingMinor\n\t\t\t\t\t\t\t\t? 'none'\n\t\t\t\t\t\t\t\t: '0 0 0 9999px rgba(0, 0, 0, 0.4), 0 0 0 3px rgba(255, 255, 255, 0.8), 0 0 20px 8px rgba(255, 255, 255, 0.4)',\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\tfontSize: '14px',\n\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t}}\n\t\t\t\t\tlocale={{\n\t\t\t\t\t\tback: 'Back',\n\t\t\t\t\t\tclose: 'Close',\n\t\t\t\t\t\tlast: 'Close',\n\t\t\t\t\t\tnext: 'Next',\n\t\t\t\t\t\tskip: 'Skip',\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t<VideoModal\n\t\t\t\tisOpen={isVideoModalOpen}\n\t\t\t\tvideoUrl={videoUrl}\n\t\t\t\tonClose={() => {\n\t\t\t\t\tsetIsVideoModalOpen(false);\n\t\t\t\t\tsetVideoUrl('');\n\t\t\t\t\tsetBlockPopups(false);\n\n\t\t\t\t\t// After video modal closes, check if there are more features to show\n\t\t\t\t\tconst nextFeature = availableMinorFeatures.find(\n\t\t\t\t\t\t(f) => !shownMinorFeatureIds.has(f.id),\n\t\t\t\t\t);\n\n\t\t\t\t\tif (nextFeature) {\n\t\t\t\t\t\t// Auto-advance to next feature after video\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\tshowMinorUpdateJoyride(nextFeature, availableMinorFeatures);\n\t\t\t\t\t\t}, 300);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// No more features to show\n\t\t\t\t\t\tsetMinorFeaturesSkipped(true);\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t/>\n\t\t</>\n\t);\n\n};\n\nexport default FeatureAnnouncementProvider;\n"],"names":["_ref","children","fetchVisibleFeatures","getStoreFeatureProgress","fetchFeatureById","markFeatureAsViewedForStore","isFeatureApplicableToCurrentPage","module","router","storeId","onAnnouncementShown","onAnnouncementInteracted","majorUpdateFeatures","minorUpdateFeatures","isLoading","markFeatureAsViewed","useFeatureAnnouncements","currentMajorFeature","setCurrentMajorFeature","useState","currentMinorFeature","setCurrentMinorFeature","runJoyride","setRunJoyride","joyrideSteps","setJoyrideSteps","runMajorJoyride","setRunMajorJoyride","majorJoyrideSteps","setMajorJoyrideSteps","isProcessingMajorUpdate","setIsProcessingMajorUpdate","isProcessingMinorUpdate","setIsProcessingMinorUpdate","availableMinorFeatures","setAvailableMinorFeatures","minorFeaturesSkipped","setMinorFeaturesSkipped","showMinorUpdates","setShowMinorUpdates","isVideoModalOpen","setIsVideoModalOpen","videoUrl","setVideoUrl","blockPopups","setBlockPopups","isClosingMajor","setIsClosingMajor","isClosingMinor","setIsClosingMinor","majorJoyrideKey","setMajorJoyrideKey","minorJoyrideKey","setMinorJoyrideKey","shownMinorFeatureIds","setShownMinorFeatureIds","Set","useEffect","styleId","styleElement","document","getElementById","createElement","id","head","appendChild","textContent","el","remove","prev","pathname","length","attempts","MAX_ATTEMPTS","checkWhatsNewButton","querySelector","showMajorUpdateJoyride","setTimeout","featureIdFromQuery","_a","query","forcedFeature","find","f","featureTag","interval","setInterval","targetSelector","startsWith","testModeFeatures","showMinorUpdateJoyride","clearInterval","observer","scrollListener","checkTimeout","isCleanedUp","checkElementsAndStartTour","availableFeatures","filter","feature","trim","has","disconnect","window","removeEventListener","clearTimeout","MutationObserver","mutations","shouldCheck","mutation","type","addedNodes","i","node","nodeType","Node","ELEMENT_NODE","element","requestAnimationFrame","observe","body","childList","subtree","addEventListener","passive","currentIndex","findIndex","totalFeatures","majorSteps","target","SELECTORS","WHATS_NEW_BUTTON","content","_jsx","jsx","MajorUpdatePopup","onSkip","handleSkipMajorUpdate","onExplore","triggeredAction","handleExploreFeature","onPrevious","handlePreviousMajorUpdate","onNext","handleNextMajorUpdate","setIsClosing","placement","placementBeacon","disableBeacon","hideCloseButton","hideSkipButton","hideFooter","offset","data","isMajor","styles","tooltip","padding","backgroundColor","borderRadius","border","boxShadow","tooltipContent","buttonNext","display","buttonBack","buttonClose","buttonSkip","announcementId","announcementTitle","title","imageUrl","displayImage","image","productVideo","useCallback","__awaiter","targetFeature","Promise","all","map","majorFeature","buttonClicked","buttonName","buttonUrl","undefined","action","_b","primaryButton","url","_c","redirectionUrl","redirectUrl","location","href","buttonText","prevFeature","prevIndex","updatedSteps","nextFeature","nextIndex","showMajorUpdatePopup","handleMajorJoyrideCallback","ACTIONS","CLOSE","forEach","handleMinorJoyrideCallback","featuresToUse","features","targetElement","scrollToElementSmooth","resolve","then","require","error","minorSteps","MinorUpdatePopup","handleSkipMinorUpdate","handleExploreMinorFeature","handlePreviousMinorUpdate","handleNextMinorUpdate","isMinor","add","_d","_e","_jsxs","_Fragment","Joyride","steps","run","continuous","showProgress","showSkipButton","callback","disableOverlayClose","disableCloseOnEsc","disableOverlay","spotlightClicks","options","primaryColor","zIndex","width","arrowColor","overlay","spotlight","fontSize","locale","back","close","last","next","skip","scrollToFirstStep","scrollOffset","disableScrolling","VideoModal","isOpen","onClose"],"mappings":"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"}
1
+ {"version":3,"file":"FeatureAnnouncementProvider.js","sources":["../../../../src/components/feature-announcements/FeatureAnnouncementProvider.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useState } from 'react';\nimport Joyride, { ACTIONS } from 'react-joyride';\nimport { SELECTORS } from './constants';\nimport { useFeatureAnnouncements } from './hooks';\nimport MajorUpdatePopup from './MajorUpdatePopup';\nimport MinorUpdatePopup from './MinorUpdatePopup';\nimport { FeatureAnnouncement, FeatureAnnouncementProviderProps } from './types';\nimport { VideoModal } from './VideoModal';\n\nconst FeatureAnnouncementProvider: React.FC<\n\tFeatureAnnouncementProviderProps\n> = ({\n\tchildren,\n\tfetchVisibleFeatures,\n\tgetStoreFeatureProgress,\n\tfetchFeatureById,\n\tmarkFeatureAsViewedForStore,\n\tisFeatureApplicableToCurrentPage,\n\tmodule,\n\trouter,\n\tstoreId,\n\tonAnnouncementShown,\n\tonAnnouncementInteracted,\n}) => {\n\tconst {\n\t\tmajorUpdateFeatures,\n\t\tminorUpdateFeatures,\n\t\tisLoading,\n\t\tmarkFeatureAsViewed,\n\t} = useFeatureAnnouncements({\n\t\tfetchVisibleFeatures,\n\t\tgetStoreFeatureProgress,\n\t\tfetchFeatureById,\n\t\tmarkFeatureAsViewedForStore,\n\t\tisFeatureApplicableToCurrentPage,\n\t\tmodule,\n\t\trouter,\n\t});\n\n\tconst [currentMajorFeature, setCurrentMajorFeature] =\n\t\tuseState<FeatureAnnouncement | null>(null);\n\tconst [currentMinorFeature, setCurrentMinorFeature] =\n\t\tuseState<FeatureAnnouncement | null>(null);\n\tconst [runJoyride, setRunJoyride] = useState(false);\n\tconst [joyrideSteps, setJoyrideSteps] = useState<any[]>([]);\n\tconst [runMajorJoyride, setRunMajorJoyride] = useState(false);\n\tconst [majorJoyrideSteps, setMajorJoyrideSteps] = useState<any[]>([]);\n\tconst [isProcessingMajorUpdate, setIsProcessingMajorUpdate] = useState(false);\n\tconst [isProcessingMinorUpdate, setIsProcessingMinorUpdate] = useState(false);\n\tconst [availableMinorFeatures, setAvailableMinorFeatures] = useState<\n\t\tFeatureAnnouncement[]\n\t>([]);\n\tconst [minorFeaturesSkipped, setMinorFeaturesSkipped] = useState(false);\n\tconst [showMinorUpdates, setShowMinorUpdates] = useState(false);\n\tconst [isVideoModalOpen, setIsVideoModalOpen] = useState(false);\n\tconst [videoUrl, setVideoUrl] = useState('');\n\tconst [blockPopups, setBlockPopups] = useState(false);\n\tconst [isClosingMajor, setIsClosingMajor] = useState(false);\n\tconst [isClosingMinor, setIsClosingMinor] = useState(false);\n\tconst [majorJoyrideKey, setMajorJoyrideKey] = useState(0);\n\tconst [minorJoyrideKey, setMinorJoyrideKey] = useState(0);\n\tconst [shownMinorFeatureIds, setShownMinorFeatureIds] = useState<Set<string>>(\n\t\tnew Set(),\n\t);\n\n\t// Add custom style for spotlight cutout effect\n\tuseEffect(() => {\n\t\tconst styleId = 'minor-spotlight-cutout-style';\n\t\tlet styleElement = document.getElementById(styleId) as HTMLStyleElement;\n\n\t\tif (!styleElement) {\n\t\t\tstyleElement = document.createElement('style');\n\t\t\tstyleElement.id = styleId;\n\t\t\tdocument.head.appendChild(styleElement);\n\t\t}\n\n\t\tstyleElement.textContent = `\n\t\t\t.react-joyride__spotlight {\n\t\t\t\ttransition: box-shadow 0.3s ease-in-out !important;\n\t\t\t\twill-change: box-shadow, transform;\n\t\t\t\ttransform: translateZ(0);\n\t\t\t}\n\t\t\t.react-joyride__tooltip {\n\t\t\t\twill-change: transform, opacity;\n\t\t\t\ttransform: translateZ(0);\n\t\t\t}\n\t\t\t.react-joyride__floater {\n\t\t\t\tright: 12px !important;\n\t\t\t\tleft: auto !important;\n\t\t\t}\n\t\t`;\n\n\t\treturn () => {\n\t\t\tconst el = document.getElementById(styleId);\n\t\t\tif (el) {\n\t\t\t\tel.remove();\n\t\t\t}\n\t\t};\n\t}, []);\n\n\t// Force Joyride remount on navigation to prevent stale state\n\tuseEffect(() => {\n\t\tsetMajorJoyrideKey((prev) => prev + 1);\n\t\tsetMinorJoyrideKey((prev) => prev + 1);\n\t\tsetIsClosingMajor(false);\n\t\tsetIsClosingMinor(false);\n\t\t// Reset session tracking on navigation to allow features to show on new pages\n\t\tsetShownMinorFeatureIds(new Set());\n\t}, [router?.pathname]);\n\n\tuseEffect(() => {\n\t\tif (\n\t\t\tmajorUpdateFeatures.length > 0 &&\n\t\t\t!currentMajorFeature &&\n\t\t\t!isLoading &&\n\t\t\t!isProcessingMajorUpdate &&\n\t\t\t!blockPopups\n\t\t) {\n\t\t\tsetShowMinorUpdates(false);\n\t\t\tsetMinorFeaturesSkipped(false);\n\t\t\tsetRunJoyride(false);\n\t\t\tsetJoyrideSteps([]);\n\t\t\tsetCurrentMinorFeature(null);\n\t\t\tsetAvailableMinorFeatures([]);\n\n\t\t\tlet attempts = 0;\n\t\t\tconst MAX_ATTEMPTS = 10;\n\n\t\t\tconst checkWhatsNewButton = () => {\n\t\t\t\tattempts++;\n\t\t\t\tconst whatsNewButton = document.querySelector(\n\t\t\t\t\t'[data-testid=\"whats-new-button\"]',\n\t\t\t\t);\n\n\t\t\t\tif (whatsNewButton) {\n\t\t\t\t\tshowMajorUpdateJoyride(majorUpdateFeatures[0]);\n\t\t\t\t} else if (attempts < MAX_ATTEMPTS) {\n\t\t\t\t\tsetTimeout(checkWhatsNewButton, 1000);\n\t\t\t\t} else {\n\t\t\t\t\tsetShowMinorUpdates(true);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tcheckWhatsNewButton();\n\t\t} else if (majorUpdateFeatures.length === 0 && !isLoading) {\n\t\t\tsetShowMinorUpdates(true);\n\t\t}\n\t}, [\n\t\tmajorUpdateFeatures,\n\t\tcurrentMajorFeature,\n\t\tisLoading,\n\t\tisProcessingMajorUpdate,\n\t\tblockPopups,\n\t]);\n\n\tuseEffect(() => {\n\t\t// Only run this special logic if a feature is being forced via URL\n\t\tconst featureIdFromQuery = router?.query?.['featureId'] as string;\n\n\t\tif (!featureIdFromQuery || isLoading || minorUpdateFeatures.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst forcedFeature = minorUpdateFeatures.find(\n\t\t\t(f) => f.id === featureIdFromQuery,\n\t\t);\n\n\t\tif (!forcedFeature || !forcedFeature.featureTag) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Prevent the standard flow from interfering\n\t\tsetMinorFeaturesSkipped(true);\n\t\t// Mark that we're processing to prevent other effects from interfering\n\t\tsetIsProcessingMinorUpdate(true);\n\n\t\tlet attempts = 0;\n\t\tconst maxAttempts = 25; // 5 seconds\n\t\tconst interval = setInterval(() => {\n\t\t\tattempts++;\n\t\t\tconst targetSelector =\n\t\t\t\tforcedFeature.featureTag.startsWith('#') ||\n\t\t\t\tforcedFeature.featureTag.startsWith('.') ||\n\t\t\t\tforcedFeature.featureTag.startsWith('[')\n\t\t\t\t\t? forcedFeature.featureTag\n\t\t\t\t\t: `#${forcedFeature.featureTag}`;\n\n\t\t\tconst element = document.querySelector(targetSelector);\n\n\t\t\tif (element) {\n\t\t\t\t// In test mode, pass the feature array directly to avoid async state issues\n\t\t\t\tconst testModeFeatures = [forcedFeature];\n\t\t\t\tsetAvailableMinorFeatures(testModeFeatures);\n\t\t\t\tshowMinorUpdateJoyride(forcedFeature, testModeFeatures);\n\t\t\t\t// Don't reset processing flag here - let user interaction handle it\n\t\t\t\t// This prevents auto-closing when multiple popups exist or when scrolling\n\t\t\t\tclearInterval(interval);\n\t\t\t} else if (attempts >= maxAttempts) {\n\t\t\t\t// Fallback for safety, though user expects it to be there.\n\t\t\t\t// We could log an error here.\n\t\t\t\t// Only reset on timeout (element not found)\n\t\t\t\tsetIsProcessingMinorUpdate(false);\n\t\t\t\tclearInterval(interval);\n\t\t\t}\n\t\t}, 200);\n\n\t\treturn () => {\n\t\t\tclearInterval(interval);\n\t\t\t// Don't reset processing flag on cleanup - it causes premature popup closure\n\t\t\t// The flag will be managed by user interactions (skip/explore handlers)\n\t\t};\n\t}, [minorUpdateFeatures, router?.query?.['featureId'], isLoading]);\n\n\tuseEffect(() => {\n\t\tif (\n\t\t\tminorUpdateFeatures.length > 0 &&\n\t\t\t!isLoading &&\n\t\t\t!runJoyride &&\n\t\t\t!isProcessingMinorUpdate &&\n\t\t\t!currentMinorFeature &&\n\t\t\t!minorFeaturesSkipped &&\n\t\t\tshowMinorUpdates &&\n\t\t\t!blockPopups\n\t\t) {\n\t\t\tlet observer: MutationObserver | null = null;\n\t\t\tlet scrollListener: (() => void) | null = null;\n\t\t\tlet checkTimeout: ReturnType<typeof setTimeout> | null = null;\n\t\t\tlet isCleanedUp = false;\n\n\t\t\tconst checkElementsAndStartTour = () => {\n\t\t\t\tif (\n\t\t\t\t\tisCleanedUp ||\n\t\t\t\t\tisProcessingMinorUpdate ||\n\t\t\t\t\tcurrentMinorFeature ||\n\t\t\t\t\tminorFeaturesSkipped ||\n\t\t\t\t\t!showMinorUpdates\n\t\t\t\t)\n\t\t\t\t\treturn;\n\n\t\t\t\tconst availableFeatures = minorUpdateFeatures.filter((feature) => {\n\t\t\t\t\tif (!feature.featureTag || feature.featureTag.trim() === '') {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Skip features already shown in this session\n\t\t\t\t\tif (shownMinorFeatureIds.has(feature.id)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst targetSelector =\n\t\t\t\t\t\tfeature.featureTag.startsWith('#') ||\n\t\t\t\t\t\tfeature.featureTag.startsWith('.') ||\n\t\t\t\t\t\tfeature.featureTag.startsWith('[')\n\t\t\t\t\t\t\t? feature.featureTag\n\t\t\t\t\t\t\t: `#${feature.featureTag}`;\n\n\t\t\t\t\tconst element = document.querySelector(targetSelector);\n\t\t\t\t\treturn element !== null;\n\t\t\t\t});\n\n\t\t\t\tif (availableFeatures.length > 0) {\n\t\t\t\t\tsetAvailableMinorFeatures(availableFeatures);\n\t\t\t\t\t// Pass features directly to avoid async state issues\n\t\t\t\t\tshowMinorUpdateJoyride(availableFeatures[0], availableFeatures);\n\n\t\t\t\t\tif (observer) {\n\t\t\t\t\t\tobserver.disconnect();\n\t\t\t\t\t\tobserver = null;\n\t\t\t\t\t}\n\t\t\t\t\tif (scrollListener) {\n\t\t\t\t\t\twindow.removeEventListener('scroll', scrollListener);\n\t\t\t\t\t\tscrollListener = null;\n\t\t\t\t\t}\n\t\t\t\t\tif (checkTimeout) {\n\t\t\t\t\t\tclearTimeout(checkTimeout);\n\t\t\t\t\t\tcheckTimeout = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tobserver = new MutationObserver((mutations) => {\n\t\t\t\tlet shouldCheck = false;\n\t\t\t\tfor (const mutation of mutations) {\n\t\t\t\t\tif (mutation.type === 'childList' && mutation.addedNodes.length > 0) {\n\t\t\t\t\t\tfor (let i = 0; i < mutation.addedNodes.length; i++) {\n\t\t\t\t\t\t\tconst node = mutation.addedNodes[i];\n\t\t\t\t\t\t\tif (node.nodeType === Node.ELEMENT_NODE) {\n\t\t\t\t\t\t\t\tconst element = node as Element;\n\t\t\t\t\t\t\t\tif (element.id || element.querySelector('[id]')) {\n\t\t\t\t\t\t\t\t\tshouldCheck = true;\n\t\t\t\t\t\t\t\t\tbreak;\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}\n\t\t\t\t\tif (shouldCheck) break;\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\t!runJoyride &&\n\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\tshowMinorUpdates &&\n\t\t\t\t\tshouldCheck\n\t\t\t\t) {\n\t\t\t\t\tif (checkTimeout) {\n\t\t\t\t\t\tclearTimeout(checkTimeout);\n\t\t\t\t\t}\n\t\t\t\t\tcheckTimeout = setTimeout(() => {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\t\t\tshowMinorUpdates\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tcheckElementsAndStartTour();\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 200);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tscrollListener = () => {\n\t\t\t\tif (\n\t\t\t\t\t!runJoyride &&\n\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\tshowMinorUpdates\n\t\t\t\t) {\n\t\t\t\t\tif (checkTimeout) {\n\t\t\t\t\t\tclearTimeout(checkTimeout);\n\t\t\t\t\t}\n\t\t\t\t\t// Use RAF for smoother performance synced with browser paint\n\t\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\t\tcheckTimeout = setTimeout(() => {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\t\t\t\tshowMinorUpdates\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tcheckElementsAndStartTour();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, 300);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif (observer) {\n\t\t\t\tobserver.observe(document.body, {\n\t\t\t\t\tchildList: true,\n\t\t\t\t\tsubtree: true,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (scrollListener) {\n\t\t\t\twindow.addEventListener('scroll', scrollListener, { passive: true });\n\t\t\t}\n\n\t\t\tcheckElementsAndStartTour();\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (\n\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\tshowMinorUpdates\n\t\t\t\t) {\n\t\t\t\t\tcheckElementsAndStartTour();\n\t\t\t\t}\n\t\t\t}, 100);\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (\n\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\tshowMinorUpdates\n\t\t\t\t) {\n\t\t\t\t\tcheckElementsAndStartTour();\n\t\t\t\t}\n\t\t\t}, 1000);\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (\n\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\tshowMinorUpdates\n\t\t\t\t) {\n\t\t\t\t\tcheckElementsAndStartTour();\n\t\t\t\t}\n\t\t\t}, 500);\n\n\t\t\treturn () => {\n\t\t\t\tisCleanedUp = true;\n\t\t\t\tif (observer) {\n\t\t\t\t\tobserver.disconnect();\n\t\t\t\t}\n\t\t\t\tif (scrollListener) {\n\t\t\t\t\twindow.removeEventListener('scroll', scrollListener);\n\t\t\t\t}\n\t\t\t\tif (checkTimeout) {\n\t\t\t\t\tclearTimeout(checkTimeout);\n\t\t\t\t}\n\t\t\t};\n\t\t} else if (minorUpdateFeatures.length === 0 || isLoading) {\n\t\t\t// Don't clear joyride if we're in test mode with an active feature\n\t\t\tconst featureIdFromQuery = router?.query?.['featureId'] as string;\n\t\t\tconst isTestModeWithActiveFeature =\n\t\t\t\tfeatureIdFromQuery && currentMinorFeature;\n\n\t\t\tif (!isTestModeWithActiveFeature) {\n\t\t\t\tsetRunJoyride(false);\n\t\t\t\tsetJoyrideSteps([]);\n\t\t\t\tsetCurrentMinorFeature(null);\n\t\t\t\tsetAvailableMinorFeatures([]);\n\t\t\t\tsetMinorFeaturesSkipped(false);\n\t\t\t}\n\t\t}\n\t}, [\n\t\tminorUpdateFeatures,\n\t\tisLoading,\n\t\trunJoyride,\n\t\tisProcessingMinorUpdate,\n\t\tcurrentMinorFeature,\n\t\tminorFeaturesSkipped,\n\t\tshowMinorUpdates,\n\t\tmarkFeatureAsViewed,\n\t\tblockPopups,\n\t]);\n\n\tconst showMajorUpdateJoyride = (feature) => {\n\t\tsetCurrentMajorFeature(feature);\n\n\t\tconst currentIndex = majorUpdateFeatures.findIndex(\n\t\t\t(f) => f.id === feature.id,\n\t\t);\n\t\tconst totalFeatures = majorUpdateFeatures.length;\n\n\t\tconst majorSteps = [\n\t\t\t{\n\t\t\t\ttarget: SELECTORS.WHATS_NEW_BUTTON,\n\t\t\t\tcontent: (\n\t\t\t\t\t<MajorUpdatePopup\n\t\t\t\t\t\tfeature={feature}\n\t\t\t\t\t\tcurrentIndex={currentIndex}\n\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\tonSkip={() => handleSkipMajorUpdate(feature)}\n\t\t\t\t\t\tonExplore={(triggeredAction) =>\n\t\t\t\t\t\t\thandleExploreFeature(feature, triggeredAction)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tonPrevious={() => handlePreviousMajorUpdate(feature)}\n\t\t\t\t\t\tonNext={() => handleNextMajorUpdate(feature)}\n\t\t\t\t\t\tsetIsClosing={setIsClosingMajor}\n\t\t\t\t\t/>\n\t\t\t\t),\n\t\t\t\tplacement: 'bottom-start',\n\t\t\t\tplacementBeacon: 'top-end',\n\t\t\t\tdisableBeacon: true,\n\t\t\t\thideCloseButton: true,\n\t\t\t\thideSkipButton: true,\n\t\t\t\thideFooter: true,\n\t\t\t\toffset: 0,\n\t\t\t\tdata: { feature, isMajor: true },\n\t\t\t\tstyles: {\n\t\t\t\t\ttooltip: {\n\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\tborderRadius: '16px',\n\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t},\n\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t},\n\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\n\t\tsetMajorJoyrideSteps(majorSteps);\n\t\tsetRunMajorJoyride(true);\n\n\t\t// Fire announcement shown callback\n\t\tif (onAnnouncementShown && storeId) {\n\t\t\tonAnnouncementShown({\n\t\t\t\tstoreId,\n\t\t\t\tannouncementId: feature.id,\n\t\t\t\tannouncementTitle: feature.title,\n\t\t\t\timageUrl: feature.displayImage || feature.image,\n\t\t\t\tvideoUrl: feature.productVideo,\n\t\t\t});\n\t\t}\n\t};\n\n\tconst handleSkipMajorUpdate = useCallback(\n\t\tasync (feature) => {\n\t\t\tconst targetFeature = feature || currentMajorFeature;\n\n\t\t\tif (targetFeature) {\n\t\t\t\tsetIsProcessingMajorUpdate(true);\n\n\t\t\t\tawait Promise.all(\n\t\t\t\t\tmajorUpdateFeatures.map((majorFeature) =>\n\t\t\t\t\t\tmarkFeatureAsViewed(majorFeature.id),\n\t\t\t\t\t),\n\t\t\t\t);\n\n\t\t\t\tsetRunMajorJoyride(false);\n\t\t\t\tsetCurrentMajorFeature(null);\n\t\t\t\tsetMajorJoyrideSteps([]);\n\n\t\t\t\tsetShowMinorUpdates(true);\n\n\t\t\t\t// Fire announcement interacted callback for Skip\n\t\t\t\tif (onAnnouncementInteracted && storeId) {\n\t\t\t\t\tonAnnouncementInteracted({\n\t\t\t\t\t\tstoreId,\n\t\t\t\t\t\tannouncementId: targetFeature.id,\n\t\t\t\t\t\tannouncementTitle: targetFeature.title,\n\t\t\t\t\t\timageUrl: targetFeature.displayImage || targetFeature.image,\n\t\t\t\t\t\tvideoUrl: targetFeature.productVideo,\n\t\t\t\t\t\tbuttonClicked: 'Skip',\n\t\t\t\t\t\tbuttonName: 'Skip',\n\t\t\t\t\t\tbuttonUrl: undefined,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsetIsProcessingMajorUpdate(false);\n\t\t\t\t}, 500);\n\t\t\t} else {\n\t\t\t\t// do nothing\n\t\t\t}\n\t\t},\n\t\t[currentMajorFeature, majorUpdateFeatures, markFeatureAsViewed],\n\t);\n\n\tconst handleExploreFeature = useCallback(\n\t\tasync (feature, triggeredAction?: string) => {\n\t\t\tsetIsProcessingMajorUpdate(true);\n\t\t\t// Await so the feature is marked before any page navigation\n\t\t\tawait markFeatureAsViewed(feature.id);\n\t\t\tconst action = triggeredAction ?? feature.primaryButton?.action;\n\t\t\tif (action === 'Play Video' && feature.productVideo) {\n\t\t\t\tsetVideoUrl(feature.productVideo);\n\t\t\t\tsetIsVideoModalOpen(true);\n\t\t\t\tsetBlockPopups(true);\n\t\t\t}\n\n\t\t\tif (action === 'Open link') {\n\t\t\t\tconst url =\n\t\t\t\t\tfeature.primaryButton?.redirectionUrl || feature.redirectUrl;\n\t\t\t\tif (url && !url.startsWith('http')) {\n\t\t\t\t\twindow.location.href = url;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsetRunMajorJoyride(false);\n\t\t\tsetCurrentMajorFeature(null);\n\t\t\tsetMajorJoyrideSteps([]);\n\t\t\tconst currentIndex = majorUpdateFeatures.findIndex(\n\t\t\t\t(f) => f.id === feature.id,\n\t\t\t);\n\t\t\tconst isLastMajorUpdate = currentIndex === majorUpdateFeatures.length - 1;\n\t\t\tif (isLastMajorUpdate) {\n\t\t\t\tsetShowMinorUpdates(true);\n\t\t\t}\n\n\t\t\t// Fire announcement interacted callback for Primary button\n\t\t\tif (onAnnouncementInteracted && storeId) {\n\t\t\t\tonAnnouncementInteracted({\n\t\t\t\t\tstoreId,\n\t\t\t\t\tannouncementId: feature.id,\n\t\t\t\t\tannouncementTitle: feature.title,\n\t\t\t\t\timageUrl: feature.displayImage || feature.image,\n\t\t\t\t\tvideoUrl: feature.productVideo,\n\t\t\t\t\tbuttonClicked: 'Primary',\n\t\t\t\t\tbuttonName: feature.buttonText || 'Explore',\n\t\t\t\t\tbuttonUrl: feature.redirectUrl || feature.productVideo,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tsetIsProcessingMajorUpdate(false);\n\t\t\t}, 500);\n\t\t},\n\t\t[majorUpdateFeatures, markFeatureAsViewed],\n\t);\n\n\tconst handlePreviousMajorUpdate = useCallback(\n\t\t(feature) => {\n\t\t\tconst targetFeature = feature || currentMajorFeature;\n\n\t\t\tif (!targetFeature) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst currentIndex = majorUpdateFeatures.findIndex(\n\t\t\t\t(f) => f.id === targetFeature.id,\n\t\t\t);\n\n\t\t\tif (currentIndex > 0) {\n\t\t\t\tconst prevFeature = majorUpdateFeatures[currentIndex - 1];\n\t\t\t\tsetCurrentMajorFeature(prevFeature);\n\n\t\t\t\tconst prevIndex = currentIndex - 1;\n\t\t\t\tconst totalFeatures = majorUpdateFeatures.length;\n\n\t\t\t\tconst updatedSteps = [\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget: '[data-testid=\"whats-new-button\"]',\n\t\t\t\t\t\tcontent: (\n\t\t\t\t\t\t\t<MajorUpdatePopup\n\t\t\t\t\t\t\t\tfeature={prevFeature}\n\t\t\t\t\t\t\t\tcurrentIndex={prevIndex}\n\t\t\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\t\t\tonSkip={() => handleSkipMajorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tonExplore={(triggeredAction) =>\n\t\t\t\t\t\t\t\t\thandleExploreFeature(prevFeature, triggeredAction)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tonPrevious={() => handlePreviousMajorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tonNext={() => handleNextMajorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tsetIsClosing={setIsClosingMajor}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t\tplacement: 'bottom-start',\n\t\t\t\t\t\tplacementBeacon: 'top-end',\n\t\t\t\t\t\tdisableBeacon: true,\n\t\t\t\t\t\thideCloseButton: true,\n\t\t\t\t\t\thideSkipButton: true,\n\t\t\t\t\t\thideFooter: true,\n\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\tdata: { feature: prevFeature, isMajor: true },\n\t\t\t\t\t\tstyles: {\n\t\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\tborderRadius: '16px',\n\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t];\n\n\t\t\t\tsetMajorJoyrideSteps(updatedSteps);\n\t\t\t} else {\n\t\t\t\t// do nothing\n\t\t\t}\n\t\t},\n\t\t[currentMajorFeature, majorUpdateFeatures],\n\t);\n\n\tconst handleNextMajorUpdate = useCallback(\n\t\t(feature) => {\n\t\t\tconst targetFeature = feature || currentMajorFeature;\n\n\t\t\tif (!targetFeature) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst currentIndex = majorUpdateFeatures.findIndex(\n\t\t\t\t(f) => f.id === targetFeature.id,\n\t\t\t);\n\n\t\t\tif (currentIndex < majorUpdateFeatures.length - 1) {\n\t\t\t\tconst nextFeature = majorUpdateFeatures[currentIndex + 1];\n\t\t\t\tsetCurrentMajorFeature(nextFeature);\n\n\t\t\t\tconst nextIndex = currentIndex + 1;\n\t\t\t\tconst totalFeatures = majorUpdateFeatures.length;\n\n\t\t\t\tconst updatedSteps = [\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget: '[data-testid=\"whats-new-button\"]',\n\t\t\t\t\t\tcontent: (\n\t\t\t\t\t\t\t<MajorUpdatePopup\n\t\t\t\t\t\t\t\tfeature={nextFeature}\n\t\t\t\t\t\t\t\tcurrentIndex={nextIndex}\n\t\t\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\t\t\tonSkip={() => handleSkipMajorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tonExplore={(triggeredAction) =>\n\t\t\t\t\t\t\t\t\thandleExploreFeature(nextFeature, triggeredAction)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tonPrevious={() => handlePreviousMajorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tonNext={() => handleNextMajorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tsetIsClosing={setIsClosingMajor}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t\tplacement: 'bottom-start',\n\t\t\t\t\t\tplacementBeacon: 'top-end',\n\t\t\t\t\t\tdisableBeacon: true,\n\t\t\t\t\t\thideCloseButton: true,\n\t\t\t\t\t\thideSkipButton: true,\n\t\t\t\t\t\thideFooter: true,\n\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\tdata: { feature: nextFeature, isMajor: true },\n\t\t\t\t\t\tstyles: {\n\t\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\tborderRadius: '16px',\n\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t];\n\n\t\t\t\tsetMajorJoyrideSteps(updatedSteps);\n\t\t\t} else {\n\t\t\t\tsetIsProcessingMajorUpdate(true);\n\n\t\t\t\tmarkFeatureAsViewed(targetFeature.id);\n\t\t\t\tsetRunMajorJoyride(false);\n\t\t\t\tsetCurrentMajorFeature(null);\n\t\t\t\tsetMajorJoyrideSteps([]);\n\n\t\t\t\tsetShowMinorUpdates(true);\n\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsetIsProcessingMajorUpdate(false);\n\t\t\t\t}, 500);\n\t\t\t}\n\t\t},\n\t\t[currentMajorFeature, majorUpdateFeatures, markFeatureAsViewed],\n\t);\n\n\tconst showMajorUpdatePopup = () => {\n\t\tif (majorUpdateFeatures.length > 0 && !currentMajorFeature) {\n\t\t\tconst whatsNewButton = document.querySelector(\n\t\t\t\t'[data-testid=\"whats-new-button\"]',\n\t\t\t);\n\n\t\t\tif (whatsNewButton) {\n\t\t\t\tshowMajorUpdateJoyride(majorUpdateFeatures[0]);\n\t\t\t}\n\t\t}\n\t};\n\n\tuseEffect(() => {\n\t\t(window as any).showMajorUpdatePopup = showMajorUpdatePopup;\n\t\treturn () => {\n\t\t\tdelete (window as any).showMajorUpdatePopup;\n\t\t};\n\t}, [majorUpdateFeatures, currentMajorFeature]);\n\tconst handleMajorJoyrideCallback = useCallback(\n\t\t(data) => {\n\t\t\tconst { action } = data;\n\n\t\t\tif (action === ACTIONS.CLOSE) {\n\t\t\t\tif (currentMajorFeature) {\n\t\t\t\t\tsetIsProcessingMajorUpdate(true);\n\n\t\t\t\t\tmajorUpdateFeatures.forEach((majorFeature) => {\n\t\t\t\t\t\tmarkFeatureAsViewed(majorFeature.id);\n\t\t\t\t\t});\n\n\t\t\t\t\tsetShowMinorUpdates(true);\n\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tsetIsProcessingMajorUpdate(false);\n\t\t\t\t\t}, 500);\n\t\t\t\t}\n\n\t\t\t\tsetRunMajorJoyride(false);\n\t\t\t\tsetCurrentMajorFeature(null);\n\t\t\t\tsetMajorJoyrideSteps([]);\n\t\t\t}\n\t\t},\n\t\t[currentMajorFeature, majorUpdateFeatures, markFeatureAsViewed],\n\t);\n\n\tconst handleMinorJoyrideCallback = useCallback(\n\t\t(data) => {\n\t\t\tconst { action } = data;\n\n\t\t\tif (action === ACTIONS.CLOSE) {\n\t\t\t\tif (currentMinorFeature) {\n\t\t\t\t\tsetIsProcessingMinorUpdate(true);\n\n\t\t\t\t\t// Only mark the current feature as viewed, not all features\n\t\t\t\t\tmarkFeatureAsViewed(currentMinorFeature.id);\n\n\t\t\t\t\t// Check if there are more features to show\n\t\t\t\t\tconst currentIndex = availableMinorFeatures.findIndex(\n\t\t\t\t\t\t(f) => f.id === currentMinorFeature.id,\n\t\t\t\t\t);\n\t\t\t\t\tconst isLastFeature =\n\t\t\t\t\t\tcurrentIndex === availableMinorFeatures.length - 1;\n\n\t\t\t\t\tif (isLastFeature) {\n\t\t\t\t\t\t// Only skip remaining features if this was the last one\n\t\t\t\t\t\tsetMinorFeaturesSkipped(true);\n\t\t\t\t\t}\n\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tsetIsProcessingMinorUpdate(false);\n\t\t\t\t\t}, 500);\n\t\t\t\t}\n\n\t\t\t\tsetRunJoyride(false);\n\t\t\t\tsetCurrentMinorFeature(null);\n\t\t\t\tsetJoyrideSteps([]);\n\t\t\t}\n\t\t},\n\t\t[currentMinorFeature, availableMinorFeatures, markFeatureAsViewed],\n\t);\n\tconst showMinorUpdateJoyride = async (feature, featuresToUse?) => {\n\t\tsetCurrentMinorFeature(feature);\n\n\t\t// Use provided features array or fall back to state (for test mode)\n\t\tconst features = featuresToUse || availableMinorFeatures;\n\t\tconst currentIndex = features.findIndex((f) => f.id === feature.id);\n\t\tconst totalFeatures = features.length;\n\n\t\tconst targetSelector =\n\t\t\tfeature.featureTag.startsWith('#') ||\n\t\t\tfeature.featureTag.startsWith('.') ||\n\t\t\tfeature.featureTag.startsWith('[')\n\t\t\t\t? feature.featureTag\n\t\t\t\t: `#${feature.featureTag}`;\n\n\t\t// Scroll to target element smoothly before showing popup\n\t\tconst targetElement = document.querySelector(targetSelector);\n\t\tif (targetElement) {\n\t\t\ttry {\n\t\t\t\t// Dynamically import to avoid circular dependencies\n\t\t\t\tconst { scrollToElementSmooth } = await import(\n\t\t\t\t\t'./utils/elementHelpers'\n\t\t\t\t);\n\t\t\t\tawait scrollToElementSmooth(targetElement, 120);\n\t\t\t} catch (error) {\n\t\t\t\t// Scroll failed silently\n\t\t\t}\n\t\t}\n\n\t\tconst minorSteps = [\n\t\t\t{\n\t\t\t\ttarget: targetSelector,\n\t\t\t\tcontent: (\n\t\t\t\t\t<MinorUpdatePopup\n\t\t\t\t\t\tfeature={feature}\n\t\t\t\t\t\tcurrentIndex={currentIndex}\n\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\tonSkip={() => handleSkipMinorUpdate(feature)}\n\t\t\t\t\t\tonExplore={(triggeredAction) =>\n\t\t\t\t\t\t\thandleExploreMinorFeature(feature, triggeredAction)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tonPrevious={() => handlePreviousMinorUpdate(feature)}\n\t\t\t\t\t\tonNext={() => handleNextMinorUpdate(feature)}\n\t\t\t\t\t\tsetIsClosing={setIsClosingMinor}\n\t\t\t\t\t/>\n\t\t\t\t),\n\t\t\t\tplacement: 'bottom',\n\t\t\t\tplacementBeacon: 'bottom-end',\n\t\t\t\tdisableBeacon: true,\n\t\t\t\thideCloseButton: true,\n\t\t\t\thideSkipButton: true,\n\t\t\t\thideFooter: true,\n\t\t\t\toffset: 0,\n\t\t\t\tdata: { feature, isMinor: true },\n\t\t\t\tstyles: {\n\t\t\t\t\ttooltip: {\n\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t},\n\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t},\n\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\t\tsetJoyrideSteps(minorSteps);\n\t\tsetRunJoyride(true);\n\t};\n\n\tconst handleSkipMinorUpdate = useCallback(\n\t\tasync (feature) => {\n\t\t\tconst targetFeature = feature || currentMinorFeature;\n\n\t\t\tif (targetFeature) {\n\t\t\t\tsetIsProcessingMinorUpdate(true);\n\n\t\t\t\t// Only mark the current feature as viewed, not all features\n\t\t\t\tawait markFeatureAsViewed(targetFeature.id);\n\n\t\t\t\t// Add to session tracker to prevent re-showing\n\t\t\t\tsetShownMinorFeatureIds((prev) => new Set(prev).add(targetFeature.id));\n\n\t\t\t\tsetRunJoyride(false);\n\t\t\t\tsetCurrentMinorFeature(null);\n\t\t\t\tsetJoyrideSteps([]);\n\n\t\t\t\t// Find next unshown feature\n\t\t\t\tconst nextFeature = availableMinorFeatures.find(\n\t\t\t\t\t(f) => f.id !== targetFeature.id && !shownMinorFeatureIds.has(f.id),\n\t\t\t\t);\n\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsetIsProcessingMinorUpdate(false);\n\n\t\t\t\t\tif (nextFeature) {\n\t\t\t\t\t\t// Auto-advance to next feature\n\t\t\t\t\t\tshowMinorUpdateJoyride(nextFeature, availableMinorFeatures);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// No more features to show\n\t\t\t\t\t\tsetMinorFeaturesSkipped(true);\n\t\t\t\t\t}\n\t\t\t\t}, 500);\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\tcurrentMinorFeature,\n\t\t\tavailableMinorFeatures,\n\t\t\tmarkFeatureAsViewed,\n\t\t\tshownMinorFeatureIds,\n\t\t],\n\t);\n\n\tconst handleExploreMinorFeature = useCallback(\n\t\tasync (feature, triggeredAction?: string) => {\n\t\t\tsetIsProcessingMinorUpdate(true);\n\n\t\t\t// Only mark the current feature as viewed\n\t\t\t// Await so the feature is marked before any page navigation\n\t\t\tawait markFeatureAsViewed(feature.id);\n\n\t\t\t// Add to session tracker to prevent re-showing\n\t\t\tsetShownMinorFeatureIds((prev) => new Set(prev).add(feature.id));\n\n\t\t\tconst action = triggeredAction ?? feature.primaryButton?.action;\n\n\t\t\tif (action === 'Play Video' && feature.productVideo) {\n\t\t\t\tsetVideoUrl(feature.productVideo);\n\t\t\t\tsetIsVideoModalOpen(true);\n\t\t\t\tsetBlockPopups(true);\n\t\t\t}\n\n\t\t\tif (action === 'Open link') {\n\t\t\t\tconst url =\n\t\t\t\t\tfeature.primaryButton?.redirectionUrl || feature.redirectUrl;\n\t\t\t\tif (url && !url.startsWith('http')) {\n\t\t\t\t\twindow.location.href = url;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsetRunJoyride(false);\n\t\t\tsetCurrentMinorFeature(null);\n\t\t\tsetJoyrideSteps([]);\n\n\t\t\t// Find next unshown feature (only auto-advance if no video modal)\n\t\t\tconst nextFeature = availableMinorFeatures.find(\n\t\t\t\t(f) => f.id !== feature.id && !shownMinorFeatureIds.has(f.id),\n\t\t\t);\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tsetIsProcessingMinorUpdate(false);\n\n\t\t\t\t// Only auto-advance if no video modal is opened\n\t\t\t\tif (nextFeature && action !== 'Play Video') {\n\t\t\t\t\t// Auto-advance to next feature\n\t\t\t\t\tshowMinorUpdateJoyride(nextFeature, availableMinorFeatures);\n\t\t\t\t} else if (!nextFeature) {\n\t\t\t\t\t// No more features to show\n\t\t\t\t\tsetMinorFeaturesSkipped(true);\n\t\t\t\t}\n\t\t\t\t// If video modal opened, wait for user to close it before advancing\n\t\t\t}, 500);\n\t\t},\n\t\t[availableMinorFeatures, markFeatureAsViewed, shownMinorFeatureIds],\n\t);\n\n\tconst handlePreviousMinorUpdate = useCallback(\n\t\tasync (feature) => {\n\t\t\tconst targetFeature = feature || currentMinorFeature;\n\n\t\t\tif (!targetFeature) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst currentIndex = availableMinorFeatures.findIndex(\n\t\t\t\t(f) => f.id === targetFeature.id,\n\t\t\t);\n\n\t\t\tif (currentIndex > 0) {\n\t\t\t\tconst prevFeature = availableMinorFeatures[currentIndex - 1];\n\t\t\t\tsetCurrentMinorFeature(prevFeature);\n\n\t\t\t\tconst targetSelector =\n\t\t\t\t\tprevFeature.featureTag.startsWith('#') ||\n\t\t\t\t\tprevFeature.featureTag.startsWith('.') ||\n\t\t\t\t\tprevFeature.featureTag.startsWith('[')\n\t\t\t\t\t\t? prevFeature.featureTag\n\t\t\t\t\t\t: `#${prevFeature.featureTag}`;\n\n\t\t\t\t// Scroll to the previous feature element\n\t\t\t\tconst targetElement = document.querySelector(targetSelector);\n\t\t\t\tif (targetElement) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst { scrollToElementSmooth } = await import(\n\t\t\t\t\t\t\t'./utils/elementHelpers'\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait scrollToElementSmooth(targetElement, 120);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t// Scroll failed silently\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst prevIndex = currentIndex - 1;\n\t\t\t\tconst totalFeatures = availableMinorFeatures.length;\n\n\t\t\t\tconst updatedSteps = [\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget: targetSelector,\n\t\t\t\t\t\tcontent: (\n\t\t\t\t\t\t\t<MinorUpdatePopup\n\t\t\t\t\t\t\t\tfeature={prevFeature}\n\t\t\t\t\t\t\t\tcurrentIndex={prevIndex}\n\t\t\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\t\t\tonSkip={() => handleSkipMinorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tonExplore={(triggeredAction) =>\n\t\t\t\t\t\t\t\t\thandleExploreMinorFeature(prevFeature, triggeredAction)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tonPrevious={() => handlePreviousMinorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tonNext={() => handleNextMinorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tsetIsClosing={setIsClosingMinor}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t\tplacement: 'bottom',\n\t\t\t\t\t\tplacementBeacon: 'bottom-end',\n\t\t\t\t\t\tdisableBeacon: true,\n\t\t\t\t\t\thideCloseButton: true,\n\t\t\t\t\t\thideSkipButton: true,\n\t\t\t\t\t\thideFooter: true,\n\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\tdata: { feature: prevFeature, isMinor: true },\n\t\t\t\t\t\tstyles: {\n\t\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t];\n\n\t\t\t\tsetJoyrideSteps(updatedSteps);\n\t\t\t}\n\t\t},\n\t\t[currentMinorFeature, availableMinorFeatures],\n\t);\n\n\tconst handleNextMinorUpdate = useCallback(\n\t\tasync (feature) => {\n\t\t\tconst targetFeature = feature || currentMinorFeature;\n\n\t\t\tif (!targetFeature) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst currentIndex = availableMinorFeatures.findIndex(\n\t\t\t\t(f) => f.id === targetFeature.id,\n\t\t\t);\n\n\t\t\tif (currentIndex < availableMinorFeatures.length - 1) {\n\t\t\t\tconst nextFeature = availableMinorFeatures[currentIndex + 1];\n\t\t\t\tsetCurrentMinorFeature(nextFeature);\n\n\t\t\t\tconst targetSelector =\n\t\t\t\t\tnextFeature.featureTag.startsWith('#') ||\n\t\t\t\t\tnextFeature.featureTag.startsWith('.') ||\n\t\t\t\t\tnextFeature.featureTag.startsWith('[')\n\t\t\t\t\t\t? nextFeature.featureTag\n\t\t\t\t\t\t: `#${nextFeature.featureTag}`;\n\n\t\t\t\t// Scroll to the next feature element\n\t\t\t\tconst targetElement = document.querySelector(targetSelector);\n\t\t\t\tif (targetElement) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst { scrollToElementSmooth } = await import(\n\t\t\t\t\t\t\t'./utils/elementHelpers'\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait scrollToElementSmooth(targetElement, 120);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t// Scroll failed silently\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst nextIndex = currentIndex + 1;\n\t\t\t\tconst totalFeatures = availableMinorFeatures.length;\n\n\t\t\t\tconst updatedSteps = [\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget: targetSelector,\n\t\t\t\t\t\tcontent: (\n\t\t\t\t\t\t\t<MinorUpdatePopup\n\t\t\t\t\t\t\t\tfeature={nextFeature}\n\t\t\t\t\t\t\t\tcurrentIndex={nextIndex}\n\t\t\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\t\t\tonSkip={() => handleSkipMinorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tonExplore={(triggeredAction) =>\n\t\t\t\t\t\t\t\t\thandleExploreMinorFeature(nextFeature, triggeredAction)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tonPrevious={() => handlePreviousMinorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tonNext={() => handleNextMinorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tsetIsClosing={setIsClosingMinor}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t\tplacement: 'bottom',\n\t\t\t\t\t\tplacementBeacon: 'bottom-end',\n\t\t\t\t\t\tdisableBeacon: true,\n\t\t\t\t\t\thideCloseButton: true,\n\t\t\t\t\t\thideSkipButton: true,\n\t\t\t\t\t\thideFooter: true,\n\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\tdata: { feature: nextFeature, isMinor: true },\n\t\t\t\t\t\tstyles: {\n\t\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t];\n\n\t\t\t\tsetJoyrideSteps(updatedSteps);\n\t\t\t} else {\n\t\t\t\tsetIsProcessingMinorUpdate(true);\n\t\t\t\tsetMinorFeaturesSkipped(true);\n\n\t\t\t\tmarkFeatureAsViewed(targetFeature.id);\n\t\t\t\tsetRunJoyride(false);\n\t\t\t\tsetCurrentMinorFeature(null);\n\t\t\t\tsetJoyrideSteps([]);\n\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsetIsProcessingMinorUpdate(false);\n\t\t\t\t}, 500);\n\t\t\t}\n\t\t},\n\t\t[currentMinorFeature, availableMinorFeatures, markFeatureAsViewed],\n\t);\n\n\treturn (\n\t\t<>\n\t\t\t{children}\n\n\t\t\t{majorJoyrideSteps.length > 0 && (\n\t\t\t\t<Joyride\n\t\t\t\t\tkey={`major-joyride-${majorJoyrideKey}`}\n\t\t\t\t\tsteps={majorJoyrideSteps}\n\t\t\t\t\trun={runMajorJoyride}\n\t\t\t\t\tcontinuous={false}\n\t\t\t\t\tshowProgress={false}\n\t\t\t\t\tshowSkipButton={false}\n\t\t\t\t\tcallback={handleMajorJoyrideCallback}\n\t\t\t\t\tdisableOverlayClose={false}\n\t\t\t\t\tdisableCloseOnEsc={false}\n\t\t\t\t\tdisableOverlay={false}\n\t\t\t\t\tspotlightClicks={false}\n\t\t\t\t\tstyles={{\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tprimaryColor: '#007bff',\n\t\t\t\t\t\t\tzIndex: 10000,\n\t\t\t\t\t\t\twidth: 'auto',\n\t\t\t\t\t\t\tarrowColor: isClosingMajor ? 'transparent' : '#212121',\n\t\t\t\t\t\t},\n\t\t\t\t\t\toverlay: {\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tspotlight: {\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\tborderRadius: '16px',\n\t\t\t\t\t\t\tfontSize: '14px',\n\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t}}\n\t\t\t\t\tlocale={{\n\t\t\t\t\t\tback: 'Back',\n\t\t\t\t\t\tclose: 'Close',\n\t\t\t\t\t\tlast: 'Close',\n\t\t\t\t\t\tnext: 'Next',\n\t\t\t\t\t\tskip: 'Skip',\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{joyrideSteps.length > 0 && (\n\t\t\t\t<Joyride\n\t\t\t\t\tkey={`minor-joyride-${minorJoyrideKey}`}\n\t\t\t\t\tsteps={joyrideSteps}\n\t\t\t\t\trun={runJoyride}\n\t\t\t\t\tcontinuous={false}\n\t\t\t\t\tshowProgress={false}\n\t\t\t\t\tshowSkipButton={false}\n\t\t\t\t\tcallback={handleMinorJoyrideCallback}\n\t\t\t\t\tdisableOverlayClose={false}\n\t\t\t\t\tdisableCloseOnEsc={false}\n\t\t\t\t\tdisableOverlay={false}\n\t\t\t\t\tscrollToFirstStep={true}\n\t\t\t\t\tscrollOffset={120}\n\t\t\t\t\tdisableScrolling={false}\n\t\t\t\t\tstyles={{\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tprimaryColor: '#007bff',\n\t\t\t\t\t\t\tzIndex: 10000,\n\t\t\t\t\t\t\twidth: 'auto',\n\t\t\t\t\t\t\tarrowColor: isClosingMinor ? 'transparent' : '#ffffff',\n\t\t\t\t\t\t},\n\t\t\t\t\t\toverlay: {\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tspotlight: {\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\tborderRadius: '8px',\n\t\t\t\t\t\t\tboxShadow: isClosingMinor\n\t\t\t\t\t\t\t\t? 'none'\n\t\t\t\t\t\t\t\t: '0 0 0 9999px rgba(0, 0, 0, 0.4), 0 0 0 3px rgba(255, 255, 255, 0.8), 0 0 20px 8px rgba(255, 255, 255, 0.4)',\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\tfontSize: '14px',\n\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t}}\n\t\t\t\t\tlocale={{\n\t\t\t\t\t\tback: 'Back',\n\t\t\t\t\t\tclose: 'Close',\n\t\t\t\t\t\tlast: 'Close',\n\t\t\t\t\t\tnext: 'Next',\n\t\t\t\t\t\tskip: 'Skip',\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t<VideoModal\n\t\t\t\tisOpen={isVideoModalOpen}\n\t\t\t\tvideoUrl={videoUrl}\n\t\t\t\tonClose={() => {\n\t\t\t\t\tsetIsVideoModalOpen(false);\n\t\t\t\t\tsetVideoUrl('');\n\t\t\t\t\tsetBlockPopups(false);\n\n\t\t\t\t\t// After video modal closes, check if there are more features to show\n\t\t\t\t\tconst nextFeature = availableMinorFeatures.find(\n\t\t\t\t\t\t(f) => !shownMinorFeatureIds.has(f.id),\n\t\t\t\t\t);\n\n\t\t\t\t\tif (nextFeature) {\n\t\t\t\t\t\t// Auto-advance to next feature after video\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\tshowMinorUpdateJoyride(nextFeature, availableMinorFeatures);\n\t\t\t\t\t\t}, 300);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// No more features to show\n\t\t\t\t\t\tsetMinorFeaturesSkipped(true);\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t/>\n\t\t</>\n\t);\n};\n\nexport default FeatureAnnouncementProvider;\n"],"names":["_ref","children","fetchVisibleFeatures","getStoreFeatureProgress","fetchFeatureById","markFeatureAsViewedForStore","isFeatureApplicableToCurrentPage","module","router","storeId","onAnnouncementShown","onAnnouncementInteracted","majorUpdateFeatures","minorUpdateFeatures","isLoading","markFeatureAsViewed","useFeatureAnnouncements","currentMajorFeature","setCurrentMajorFeature","useState","currentMinorFeature","setCurrentMinorFeature","runJoyride","setRunJoyride","joyrideSteps","setJoyrideSteps","runMajorJoyride","setRunMajorJoyride","majorJoyrideSteps","setMajorJoyrideSteps","isProcessingMajorUpdate","setIsProcessingMajorUpdate","isProcessingMinorUpdate","setIsProcessingMinorUpdate","availableMinorFeatures","setAvailableMinorFeatures","minorFeaturesSkipped","setMinorFeaturesSkipped","showMinorUpdates","setShowMinorUpdates","isVideoModalOpen","setIsVideoModalOpen","videoUrl","setVideoUrl","blockPopups","setBlockPopups","isClosingMajor","setIsClosingMajor","isClosingMinor","setIsClosingMinor","majorJoyrideKey","setMajorJoyrideKey","minorJoyrideKey","setMinorJoyrideKey","shownMinorFeatureIds","setShownMinorFeatureIds","Set","useEffect","styleId","styleElement","document","getElementById","createElement","id","head","appendChild","textContent","el","remove","prev","pathname","length","attempts","MAX_ATTEMPTS","checkWhatsNewButton","querySelector","showMajorUpdateJoyride","setTimeout","featureIdFromQuery","_a","query","forcedFeature","find","f","featureTag","interval","setInterval","targetSelector","startsWith","testModeFeatures","showMinorUpdateJoyride","clearInterval","observer","scrollListener","checkTimeout","isCleanedUp","checkElementsAndStartTour","availableFeatures","filter","feature","trim","has","disconnect","window","removeEventListener","clearTimeout","MutationObserver","mutations","shouldCheck","mutation","type","addedNodes","i","node","nodeType","Node","ELEMENT_NODE","element","requestAnimationFrame","observe","body","childList","subtree","addEventListener","passive","currentIndex","findIndex","totalFeatures","majorSteps","target","SELECTORS","WHATS_NEW_BUTTON","content","_jsx","jsx","MajorUpdatePopup","onSkip","handleSkipMajorUpdate","onExplore","triggeredAction","handleExploreFeature","onPrevious","handlePreviousMajorUpdate","onNext","handleNextMajorUpdate","setIsClosing","placement","placementBeacon","disableBeacon","hideCloseButton","hideSkipButton","hideFooter","offset","data","isMajor","styles","tooltip","padding","backgroundColor","borderRadius","border","boxShadow","tooltipContent","buttonNext","display","buttonBack","buttonClose","buttonSkip","announcementId","announcementTitle","title","imageUrl","displayImage","image","productVideo","useCallback","__awaiter","targetFeature","Promise","all","map","majorFeature","buttonClicked","buttonName","buttonUrl","undefined","action","_b","primaryButton","url","_c","redirectionUrl","redirectUrl","location","href","buttonText","prevFeature","prevIndex","updatedSteps","nextFeature","nextIndex","showMajorUpdatePopup","handleMajorJoyrideCallback","ACTIONS","CLOSE","forEach","handleMinorJoyrideCallback","featuresToUse","features","targetElement","scrollToElementSmooth","resolve","then","require","error","minorSteps","MinorUpdatePopup","handleSkipMinorUpdate","handleExploreMinorFeature","handlePreviousMinorUpdate","handleNextMinorUpdate","isMinor","add","_d","_e","_jsxs","_Fragment","Joyride","steps","run","continuous","showProgress","showSkipButton","callback","disableOverlayClose","disableCloseOnEsc","disableOverlay","spotlightClicks","options","primaryColor","zIndex","width","arrowColor","overlay","spotlight","fontSize","locale","back","close","last","next","skip","scrollToFirstStep","scrollOffset","disableScrolling","VideoModal","isOpen","onClose"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});const t=require("../../../node_modules/@tiptap/core/dist/index.js").Extension.create({name:"sendShortcut",addOptions:()=>({onSend:void 0,sendShortcut:void 0,extraShortcuts:[]}),addKeyboardShortcuts(){var t,o;const e={};if(this.options.onSend&&this.options.sendShortcut){const o=Array.isArray(this.options.sendShortcut)?this.options.sendShortcut:[this.options.sendShortcut],s=()=>{var t,o,e;return this.options.onSend({html:this.editor.getHTML(),text:this.editor.getText(),isEmpty:this.editor.isEmpty,characterCount:null!==(e=null===(o=null===(t=this.editor.storage.characterCount)||void 0===t?void 0:t.characters)||void 0===o?void 0:o.call(t))&&void 0!==e?e:this.editor.getText().length}),!0};for(const i of o){e[[...(null!==(t=i.modifiers)&&void 0!==t?t:[]).map((t=>"mod"===t?"Mod":t.charAt(0).toUpperCase()+t.slice(1))),i.key].join("-")]=s}}for(const t of this.options.extraShortcuts){e[[...(null!==(o=t.modifiers)&&void 0!==o?o:[]).map((t=>"mod"===t?"Mod":t.charAt(0).toUpperCase()+t.slice(1))),t.key].join("-")]=()=>(t.handler(),!0)}return e}});exports.SendShortcutExtension=t;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("../../../node_modules/@tiptap/core/dist/index.js"),o=require("../../BikEditor.utils.js");const e=t.Extension.create({name:"sendShortcut",addOptions:()=>({onSend:void 0,sendShortcut:void 0,extraShortcuts:[]}),addKeyboardShortcuts(){var t,e;const s={};if(this.options.onSend&&this.options.sendShortcut){const e=Array.isArray(this.options.sendShortcut)?this.options.sendShortcut:[this.options.sendShortcut],r=()=>(this.options.onSend(o.extractContent(this.editor)),!0);for(const o of e){s[[...(null!==(t=o.modifiers)&&void 0!==t?t:[]).map((t=>"mod"===t?"Mod":t.charAt(0).toUpperCase()+t.slice(1))),o.key].join("-")]=r}}for(const t of this.options.extraShortcuts){s[[...(null!==(e=t.modifiers)&&void 0!==e?e:[]).map((t=>"mod"===t?"Mod":t.charAt(0).toUpperCase()+t.slice(1))),t.key].join("-")]=()=>(t.handler(),!0)}return s}});exports.SendShortcutExtension=e;
2
2
  //# sourceMappingURL=SendShortcutExtension.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SendShortcutExtension.js","sources":["../../../../../src/editor/extensions/sendShortcut/SendShortcutExtension.ts"],"sourcesContent":["import { Extension } from '@tiptap/core';\nimport type { EditorSnapshot, KeyboardShortcut } from '../../BikEditor.types';\n\nexport const SendShortcutExtension = Extension.create({\n\tname: 'sendShortcut',\n\taddOptions() {\n\t\treturn {\n\t\t\tonSend: undefined as ((c: EditorSnapshot) => void) | undefined,\n\t\t\tsendShortcut: undefined as\n\t\t\t\t| { key: string; modifiers?: Array<'mod' | 'ctrl' | 'shift' | 'alt'> }\n\t\t\t\t| Array<{\n\t\t\t\t\t\tkey: string;\n\t\t\t\t\t\tmodifiers?: Array<'mod' | 'ctrl' | 'shift' | 'alt'>;\n\t\t\t\t }>\n\t\t\t\t| undefined,\n\t\t\textraShortcuts: [] as KeyboardShortcut[],\n\t\t};\n\t},\n\taddKeyboardShortcuts() {\n\t\tconst map: Record<string, () => boolean> = {};\n\n\t\t// onSend shortcut(s) — only registered when sendShortcut is explicitly configured\n\t\tif (this.options.onSend && this.options.sendShortcut) {\n\t\t\tconst shortcuts = Array.isArray(this.options.sendShortcut)\n\t\t\t\t? this.options.sendShortcut\n\t\t\t\t: [this.options.sendShortcut];\n\t\t\tconst handler = () => {\n\t\t\t\tthis.options.onSend!({\n\t\t\t\t\thtml: this.editor.getHTML(),\n\t\t\t\t\ttext: this.editor.getText(),\n\t\t\t\t\tisEmpty: this.editor.isEmpty,\n\t\t\t\t\tcharacterCount:\n\t\t\t\t\t\tthis.editor.storage.characterCount?.characters?.() ??\n\t\t\t\t\t\tthis.editor.getText().length,\n\t\t\t\t});\n\t\t\t\treturn true;\n\t\t\t};\n\t\t\tfor (const sc of shortcuts) {\n\t\t\t\tconst modParts = (sc.modifiers ?? []).map((m) =>\n\t\t\t\t\tm === 'mod' ? 'Mod' : m.charAt(0).toUpperCase() + m.slice(1),\n\t\t\t\t);\n\t\t\t\tconst combo = [...modParts, sc.key].join('-');\n\t\t\t\tmap[combo] = handler;\n\t\t\t}\n\t\t}\n\n\t\t// Consumer-defined shortcuts\n\t\tfor (const shortcut of this.options.extraShortcuts) {\n\t\t\tconst modParts = (shortcut.modifiers ?? []).map((m) =>\n\t\t\t\tm === 'mod' ? 'Mod' : m.charAt(0).toUpperCase() + m.slice(1),\n\t\t\t);\n\t\t\tconst combo = [...modParts, shortcut.key].join('-');\n\t\t\tmap[combo] = () => {\n\t\t\t\tshortcut.handler();\n\t\t\t\treturn true;\n\t\t\t};\n\t\t}\n\n\t\treturn map;\n\t},\n});\n"],"names":["SendShortcutExtension","Extension","create","name","addOptions","onSend","undefined","sendShortcut","extraShortcuts","addKeyboardShortcuts","map","this","options","shortcuts","Array","isArray","handler","html","editor","getHTML","text","getText","isEmpty","characterCount","_b","_a","storage","characters","call","length","sc","modifiers","m","charAt","toUpperCase","slice","key","join","shortcut"],"mappings":"0EAGaA,8DAAiCC,UAACC,OAAO,CACrDC,KAAM,eACNC,WAAUA,KACF,CACNC,YAAQC,EACRC,kBAAcD,EAOdE,eAAgB,KAGlBC,+BACC,MAAMC,EAAqC,CAAA,EAG3C,GAAIC,KAAKC,QAAQP,QAAUM,KAAKC,QAAQL,aAAc,CACrD,MAAMM,EAAYC,MAAMC,QAAQJ,KAAKC,QAAQL,cAC1CI,KAAKC,QAAQL,aACb,CAACI,KAAKC,QAAQL,cACXS,EAAUA,eASf,OARAL,KAAKC,QAAQP,OAAQ,CACpBY,KAAMN,KAAKO,OAAOC,UAClBC,KAAMT,KAAKO,OAAOG,UAClBC,QAASX,KAAKO,OAAOI,QACrBC,yBAC+C,QAA9CC,UAAAC,EAAAd,KAAKO,OAAOQ,QAAQH,qCAAgBI,kBAAU,IAAAH,OAAA,EAAAA,EAAAI,KAAAH,kBAC9Cd,KAAKO,OAAOG,UAAUQ,UAEjB,CAAI,EAEZ,IAAK,MAAMC,KAAMjB,EAAW,CAK3BH,EADc,aAHIe,EAAAK,EAAGC,yBAAa,IAAIrB,KAAKsB,GACpC,QAANA,EAAc,MAAQA,EAAEC,OAAO,GAAGC,cAAgBF,EAAEG,MAAM,KAE/BL,EAAGM,KAAKC,KAAK,MAC5BrB,CACb,CACD,CAGD,IAAK,MAAMsB,KAAY3B,KAAKC,QAAQJ,eAAgB,CAKnDE,EADc,aAHIc,EAAAc,EAASP,yBAAa,IAAIrB,KAAKsB,GAC1C,QAANA,EAAc,MAAQA,EAAEC,OAAO,GAAGC,cAAgBF,EAAEG,MAAM,KAE/BG,EAASF,KAAKC,KAAK,MAClC,KACZC,EAAStB,WACF,EAER,CAED,OAAON,CACR"}
1
+ {"version":3,"file":"SendShortcutExtension.js","sources":["../../../../../src/editor/extensions/sendShortcut/SendShortcutExtension.ts"],"sourcesContent":["import { Extension } from '@tiptap/core';\nimport type { EditorSnapshot, KeyboardShortcut } from '../../BikEditor.types';\nimport { extractContent } from '../../BikEditor.utils';\n\nexport const SendShortcutExtension = Extension.create({\n\tname: 'sendShortcut',\n\taddOptions() {\n\t\treturn {\n\t\t\tonSend: undefined as ((c: EditorSnapshot) => void) | undefined,\n\t\t\tsendShortcut: undefined as\n\t\t\t\t| { key: string; modifiers?: Array<'mod' | 'ctrl' | 'shift' | 'alt'> }\n\t\t\t\t| Array<{\n\t\t\t\t\t\tkey: string;\n\t\t\t\t\t\tmodifiers?: Array<'mod' | 'ctrl' | 'shift' | 'alt'>;\n\t\t\t\t }>\n\t\t\t\t| undefined,\n\t\t\textraShortcuts: [] as KeyboardShortcut[],\n\t\t};\n\t},\n\taddKeyboardShortcuts() {\n\t\tconst map: Record<string, () => boolean> = {};\n\n\t\t// onSend shortcut(s) — only registered when sendShortcut is explicitly configured\n\t\tif (this.options.onSend && this.options.sendShortcut) {\n\t\t\tconst shortcuts = Array.isArray(this.options.sendShortcut)\n\t\t\t\t? this.options.sendShortcut\n\t\t\t\t: [this.options.sendShortcut];\n\t\t\tconst handler = () => {\n\t\t\t\tthis.options.onSend!(extractContent(this.editor));\n\t\t\t\treturn true;\n\t\t\t};\n\t\t\tfor (const sc of shortcuts) {\n\t\t\t\tconst modParts = (sc.modifiers ?? []).map((m) =>\n\t\t\t\t\tm === 'mod' ? 'Mod' : m.charAt(0).toUpperCase() + m.slice(1),\n\t\t\t\t);\n\t\t\t\tconst combo = [...modParts, sc.key].join('-');\n\t\t\t\tmap[combo] = handler;\n\t\t\t}\n\t\t}\n\n\t\t// Consumer-defined shortcuts\n\t\tfor (const shortcut of this.options.extraShortcuts) {\n\t\t\tconst modParts = (shortcut.modifiers ?? []).map((m) =>\n\t\t\t\tm === 'mod' ? 'Mod' : m.charAt(0).toUpperCase() + m.slice(1),\n\t\t\t);\n\t\t\tconst combo = [...modParts, shortcut.key].join('-');\n\t\t\tmap[combo] = () => {\n\t\t\t\tshortcut.handler();\n\t\t\t\treturn true;\n\t\t\t};\n\t\t}\n\n\t\treturn map;\n\t},\n});\n"],"names":["SendShortcutExtension","Extension","create","name","addOptions","onSend","undefined","sendShortcut","extraShortcuts","addKeyboardShortcuts","map","this","options","shortcuts","Array","isArray","handler","extractContent","editor","sc","_a","modifiers","m","charAt","toUpperCase","slice","key","join","shortcut","_b"],"mappings":"kLAIaA,EAAwBC,EAASA,UAACC,OAAO,CACrDC,KAAM,eACNC,WAAUA,KACF,CACNC,YAAQC,EACRC,kBAAcD,EAOdE,eAAgB,KAGlBC,+BACC,MAAMC,EAAqC,CAAA,EAG3C,GAAIC,KAAKC,QAAQP,QAAUM,KAAKC,QAAQL,aAAc,CACrD,MAAMM,EAAYC,MAAMC,QAAQJ,KAAKC,QAAQL,cAC1CI,KAAKC,QAAQL,aACb,CAACI,KAAKC,QAAQL,cACXS,EAAUA,KACfL,KAAKC,QAAQP,OAAQY,EAAcA,eAACN,KAAKO,UAClC,GAER,IAAK,MAAMC,KAAMN,EAAW,CAK3BH,EADc,aAHIU,EAAAD,EAAGE,yBAAa,IAAIX,KAAKY,GACpC,QAANA,EAAc,MAAQA,EAAEC,OAAO,GAAGC,cAAgBF,EAAEG,MAAM,KAE/BN,EAAGO,KAAKC,KAAK,MAC5BX,CACb,CACD,CAGD,IAAK,MAAMY,KAAYjB,KAAKC,QAAQJ,eAAgB,CAKnDE,EADc,aAHImB,EAAAD,EAASP,yBAAa,IAAIX,KAAKY,GAC1C,QAANA,EAAc,MAAQA,EAAEC,OAAO,GAAGC,cAAgBF,EAAEG,MAAM,KAE/BG,EAASF,KAAKC,KAAK,MAClC,KACZC,EAASZ,WACF,EAER,CAED,OAAON,CACR"}
@@ -1,2 +1,2 @@
1
- "use strict";function e(r){var a;if(r.nodeType===Node.TEXT_NODE)return null!==(a=r.textContent)&&void 0!==a?a:"";if(r.nodeType!==Node.ELEMENT_NODE)return"";const n=r,c=n.tagName.toLowerCase(),t=function(r){return Array.from(r.childNodes).map(e).join("")}(n);switch(c){case"strong":case"b":return t?`*${t}*`:"";case"em":case"i":case"s":case"del":case"strike":case"code":case"pre":case"a":case"ul":case"ol":case"body":default:return t;case"br":return"\n";case"p":case"div":return t?`${t}\n`:"\n";case"h1":case"h2":case"h3":case"h4":case"h5":case"h6":return t?`*${t}*\n`:"\n";case"li":return`• ${t.trimEnd()}\n`;case"blockquote":return t+"\n"}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.toLiveChatText=function(r){if(!r)return"";if("undefined"!=typeof document){return e((new DOMParser).parseFromString(r,"text/html").body).replace(/\n{3,}/g,"\n\n").trim()}return function(e){return e.replace(/<strong[^>]*>([\s\S]*?)<\/strong>/gi,"*$1*").replace(/<b[^>]*>([\s\S]*?)<\/b>/gi,"*$1*").replace(/<em[^>]*>([\s\S]*?)<\/em>/gi,"$1").replace(/<i[^>]*>([\s\S]*?)<\/i>/gi,"$1").replace(/<s[^>]*>([\s\S]*?)<\/s>/gi,"$1").replace(/<del[^>]*>([\s\S]*?)<\/del>/gi,"$1").replace(/<a[^>]*>([\s\S]*?)<\/a>/gi,"$1").replace(/<br\s*\/?>/gi,"\n").replace(/<\/p>/gi,"\n").replace(/<\/div>/gi,"\n").replace(/<\/h[1-6]>/gi,"\n").replace(/<li[^>]*>/gi,"• ").replace(/<\/li>/gi,"\n").replace(/<[^>]+>/g,"").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&nbsp;/g," ").replace(/\n{3,}/g,"\n\n").trim()}(r)};
1
+ "use strict";function e(r){var a,n,s;if(r.nodeType===Node.TEXT_NODE)return null!==(a=r.textContent)&&void 0!==a?a:"";if(r.nodeType!==Node.ELEMENT_NODE)return"";const c=r,t=c.tagName.toLowerCase(),i=function(r){return Array.from(r.childNodes).map(e).join("")}(c);switch(t){case"strong":case"b":return i?`*${i}*`:"";case"em":case"i":case"s":case"del":case"strike":case"code":case"pre":case"a":case"ul":case"ol":case"body":default:return i;case"br":return"\n";case"p":case"div":return 1===c.childNodes.length&&"br"===(null===(s=null===(n=c.firstChild)||void 0===n?void 0:n.tagName)||void 0===s?void 0:s.toLowerCase())?"\n":i?`${i}\n`:"\n";case"h1":case"h2":case"h3":case"h4":case"h5":case"h6":return i?`*${i}*\n`:"\n";case"li":return`• ${i.trimEnd()}\n`;case"blockquote":return i+"\n"}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.toLiveChatText=function(r){if(!r)return"";if("undefined"!=typeof document){return e((new DOMParser).parseFromString(r,"text/html").body).trim()}return function(e){return e.replace(/<strong[^>]*>([\s\S]*?)<\/strong>/gi,"*$1*").replace(/<b[^>]*>([\s\S]*?)<\/b>/gi,"*$1*").replace(/<em[^>]*>([\s\S]*?)<\/em>/gi,"$1").replace(/<i[^>]*>([\s\S]*?)<\/i>/gi,"$1").replace(/<s[^>]*>([\s\S]*?)<\/s>/gi,"$1").replace(/<del[^>]*>([\s\S]*?)<\/del>/gi,"$1").replace(/<a[^>]*>([\s\S]*?)<\/a>/gi,"$1").replace(/<p[^>]*>\s*<br\s*\/?>\s*<\/p>/gi,"\n").replace(/<br\s*\/?>/gi,"\n").replace(/<\/p>/gi,"\n").replace(/<\/div>/gi,"\n").replace(/<\/h[1-6]>/gi,"\n").replace(/<li[^>]*>/gi,"• ").replace(/<\/li>/gi,"\n").replace(/<[^>]+>/g,"").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&nbsp;/g," ").trim()}(r)};
2
2
  //# sourceMappingURL=toLiveChatText.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"toLiveChatText.js","sources":["../../../../src/editor/serializers/toLiveChatText.ts"],"sourcesContent":["/**\n * Converts TipTap HTML to LiveChat plain text.\n *\n * LiveChat supports **bold** (`*text*`) but NOT italic or strikethrough.\n * Italic and strikethrough marks are stripped — the inner text is preserved.\n * Links emit only the display text (href is dropped).\n *\n * @example\n * const { html } = ref.current?.getContent();\n * const lcText = toLiveChatText(html);\n * sendLiveChat({ text: lcText });\n */\nexport function toLiveChatText(html: string): string {\n\tif (!html) return '';\n\n\tif (typeof document !== 'undefined') {\n\t\tconst doc = new DOMParser().parseFromString(html, 'text/html');\n\t\treturn serializeNode(doc.body)\n\t\t\t.replace(/\\n{3,}/g, '\\n\\n')\n\t\t\t.trim();\n\t}\n\n\treturn ssrFallback(html);\n}\n\n// ---------------------------------------------------------------------------\n// Browser path — DOM-based, handles nested marks correctly\n// ---------------------------------------------------------------------------\n\nfunction serializeNode(node: Node): string {\n\tif (node.nodeType === Node.TEXT_NODE) return node.textContent ?? '';\n\tif (node.nodeType !== Node.ELEMENT_NODE) return '';\n\n\tconst el = node as Element;\n\tconst tag = el.tagName.toLowerCase();\n\tconst inner = serializeChildren(el);\n\n\tswitch (tag) {\n\t\tcase 'strong':\n\t\tcase 'b':\n\t\t\treturn inner ? `*${inner}*` : '';\n\n\t\t// Italic and strike: strip marks, keep inner text\n\t\tcase 'em':\n\t\tcase 'i':\n\t\tcase 's':\n\t\tcase 'del':\n\t\tcase 'strike':\n\t\t\treturn inner;\n\n\t\tcase 'code':\n\t\tcase 'pre':\n\t\t\treturn inner;\n\n\t\tcase 'a':\n\t\t\t// LiveChat does not support hyperlinks — emit display text only\n\t\t\treturn inner;\n\n\t\tcase 'br':\n\t\t\treturn '\\n';\n\n\t\tcase 'p':\n\t\tcase 'div':\n\t\t\treturn inner ? `${inner}\\n` : '\\n';\n\n\t\tcase 'h1':\n\t\tcase 'h2':\n\t\tcase 'h3':\n\t\tcase 'h4':\n\t\tcase 'h5':\n\t\tcase 'h6':\n\t\t\treturn inner ? `*${inner}*\\n` : '\\n';\n\n\t\tcase 'ul':\n\t\tcase 'ol':\n\t\t\treturn inner;\n\n\t\tcase 'li':\n\t\t\treturn `• ${inner.trimEnd()}\\n`;\n\n\t\tcase 'blockquote':\n\t\t\treturn inner + '\\n';\n\n\t\tcase 'body':\n\t\tdefault:\n\t\t\treturn inner;\n\t}\n}\n\nfunction serializeChildren(el: Element): string {\n\treturn Array.from(el.childNodes).map(serializeNode).join('');\n}\n\n// ---------------------------------------------------------------------------\n// SSR / Node.js fallback — regex-based, best-effort for simple markup\n// ---------------------------------------------------------------------------\n\nfunction ssrFallback(html: string): string {\n\treturn html\n\t\t.replace(/<strong[^>]*>([\\s\\S]*?)<\\/strong>/gi, '*$1*')\n\t\t.replace(/<b[^>]*>([\\s\\S]*?)<\\/b>/gi, '*$1*')\n\t\t.replace(/<em[^>]*>([\\s\\S]*?)<\\/em>/gi, '$1')\n\t\t.replace(/<i[^>]*>([\\s\\S]*?)<\\/i>/gi, '$1')\n\t\t.replace(/<s[^>]*>([\\s\\S]*?)<\\/s>/gi, '$1')\n\t\t.replace(/<del[^>]*>([\\s\\S]*?)<\\/del>/gi, '$1')\n\t\t.replace(/<a[^>]*>([\\s\\S]*?)<\\/a>/gi, '$1')\n\t\t.replace(/<br\\s*\\/?>/gi, '\\n')\n\t\t.replace(/<\\/p>/gi, '\\n')\n\t\t.replace(/<\\/div>/gi, '\\n')\n\t\t.replace(/<\\/h[1-6]>/gi, '\\n')\n\t\t.replace(/<li[^>]*>/gi, '• ')\n\t\t.replace(/<\\/li>/gi, '\\n')\n\t\t.replace(/<[^>]+>/g, '')\n\t\t.replace(/&amp;/g, '&')\n\t\t.replace(/&lt;/g, '<')\n\t\t.replace(/&gt;/g, '>')\n\t\t.replace(/&nbsp;/g, ' ')\n\t\t.replace(/\\n{3,}/g, '\\n\\n')\n\t\t.trim();\n}\n"],"names":["serializeNode","node","nodeType","Node","TEXT_NODE","textContent","_a","ELEMENT_NODE","el","tag","tagName","toLowerCase","inner","Array","from","childNodes","map","join","serializeChildren","trimEnd","html","document","DOMParser","parseFromString","body","replace","trim","ssrFallback"],"mappings":"aA6BA,SAASA,EAAcC,SACtB,GAAIA,EAAKC,WAAaC,KAAKC,UAAW,OAAuB,UAAhBH,EAAKI,mBAAW,IAAAC,EAAAA,EAAI,GACjE,GAAIL,EAAKC,WAAaC,KAAKI,aAAc,MAAO,GAEhD,MAAMC,EAAKP,EACLQ,EAAMD,EAAGE,QAAQC,cACjBC,EAsDP,SAA2BJ,GAC1B,OAAOK,MAAMC,KAAKN,EAAGO,YAAYC,IAAIhB,GAAeiB,KAAK,GAC1D,CAxDeC,CAAkBV,GAEhC,OAAQC,GACP,IAAK,SACL,IAAK,IACJ,OAAOG,EAAQ,IAAIA,KAAW,GAG/B,IAAK,KACL,IAAK,IACL,IAAK,IACL,IAAK,MACL,IAAK,SAGL,IAAK,OACL,IAAK,MAGL,IAAK,IAmBL,IAAK,KACL,IAAK,KASL,IAAK,OACL,QACC,OAAOA,EA3BR,IAAK,KACJ,MAAO,KAER,IAAK,IACL,IAAK,MACJ,OAAOA,EAAQ,GAAGA,MAAY,KAE/B,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACJ,OAAOA,EAAQ,IAAIA,OAAa,KAMjC,IAAK,KACJ,WAAYA,EAAMO,cAEnB,IAAK,aACJ,OAAOP,EAAQ,KAMlB,+EA3EM,SAAyBQ,GAC9B,IAAKA,EAAM,MAAO,GAElB,GAAwB,oBAAbC,SAA0B,CAEpC,OAAOrB,GADK,IAAIsB,WAAYC,gBAAgBH,EAAM,aACzBI,MACvBC,QAAQ,UAAW,QACnBC,MACF,CAED,OA2ED,SAAqBN,GACpB,OAAOA,EACLK,QAAQ,sCAAuC,QAC/CA,QAAQ,4BAA6B,QACrCA,QAAQ,8BAA+B,MACvCA,QAAQ,4BAA6B,MACrCA,QAAQ,4BAA6B,MACrCA,QAAQ,gCAAiC,MACzCA,QAAQ,4BAA6B,MACrCA,QAAQ,eAAgB,MACxBA,QAAQ,UAAW,MACnBA,QAAQ,YAAa,MACrBA,QAAQ,eAAgB,MACxBA,QAAQ,cAAe,MACvBA,QAAQ,WAAY,MACpBA,QAAQ,WAAY,IACpBA,QAAQ,SAAU,KAClBA,QAAQ,QAAS,KACjBA,QAAQ,QAAS,KACjBA,QAAQ,UAAW,KACnBA,QAAQ,UAAW,QACnBC,MACH,CAjGQC,CAAYP,EACpB"}
1
+ {"version":3,"file":"toLiveChatText.js","sources":["../../../../src/editor/serializers/toLiveChatText.ts"],"sourcesContent":["/**\n * Converts TipTap HTML to LiveChat plain text.\n *\n * LiveChat supports **bold** (`*text*`) but NOT italic or strikethrough.\n * Italic and strikethrough marks are stripped — the inner text is preserved.\n * Links emit only the display text (href is dropped).\n *\n * @example\n * const { html } = ref.current?.getContent();\n * const lcText = toLiveChatText(html);\n * sendLiveChat({ text: lcText });\n */\nexport function toLiveChatText(html: string): string {\n\tif (!html) return '';\n\n\tif (typeof document !== 'undefined') {\n\t\tconst doc = new DOMParser().parseFromString(html, 'text/html');\n\t\treturn serializeNode(doc.body).trim();\n\t}\n\n\treturn ssrFallback(html);\n}\n\n// ---------------------------------------------------------------------------\n// Browser path — DOM-based, handles nested marks correctly\n// ---------------------------------------------------------------------------\n\nfunction serializeNode(node: Node): string {\n\tif (node.nodeType === Node.TEXT_NODE) return node.textContent ?? '';\n\tif (node.nodeType !== Node.ELEMENT_NODE) return '';\n\n\tconst el = node as Element;\n\tconst tag = el.tagName.toLowerCase();\n\tconst inner = serializeChildren(el);\n\n\tswitch (tag) {\n\t\tcase 'strong':\n\t\tcase 'b':\n\t\t\treturn inner ? `*${inner}*` : '';\n\n\t\t// Italic and strike: strip marks, keep inner text\n\t\tcase 'em':\n\t\tcase 'i':\n\t\tcase 's':\n\t\tcase 'del':\n\t\tcase 'strike':\n\t\t\treturn inner;\n\n\t\tcase 'code':\n\t\tcase 'pre':\n\t\t\treturn inner;\n\n\t\tcase 'a':\n\t\t\t// LiveChat does not support hyperlinks — emit display text only\n\t\t\treturn inner;\n\n\t\tcase 'br':\n\t\t\treturn '\\n';\n\n\t\tcase 'p':\n\t\tcase 'div': {\n\t\t\tconst isBlankLine =\n\t\t\t\tel.childNodes.length === 1 &&\n\t\t\t\t(el.firstChild as Element)?.tagName?.toLowerCase() === 'br';\n\t\t\treturn isBlankLine ? '\\n' : inner ? `${inner}\\n` : '\\n';\n\t\t}\n\n\t\tcase 'h1':\n\t\tcase 'h2':\n\t\tcase 'h3':\n\t\tcase 'h4':\n\t\tcase 'h5':\n\t\tcase 'h6':\n\t\t\treturn inner ? `*${inner}*\\n` : '\\n';\n\n\t\tcase 'ul':\n\t\tcase 'ol':\n\t\t\treturn inner;\n\n\t\tcase 'li':\n\t\t\treturn `• ${inner.trimEnd()}\\n`;\n\n\t\tcase 'blockquote':\n\t\t\treturn inner + '\\n';\n\n\t\tcase 'body':\n\t\tdefault:\n\t\t\treturn inner;\n\t}\n}\n\nfunction serializeChildren(el: Element): string {\n\treturn Array.from(el.childNodes).map(serializeNode).join('');\n}\n\n// ---------------------------------------------------------------------------\n// SSR / Node.js fallback — regex-based, best-effort for simple markup\n// ---------------------------------------------------------------------------\n\nfunction ssrFallback(html: string): string {\n\treturn html\n\t\t.replace(/<strong[^>]*>([\\s\\S]*?)<\\/strong>/gi, '*$1*')\n\t\t.replace(/<b[^>]*>([\\s\\S]*?)<\\/b>/gi, '*$1*')\n\t\t.replace(/<em[^>]*>([\\s\\S]*?)<\\/em>/gi, '$1')\n\t\t.replace(/<i[^>]*>([\\s\\S]*?)<\\/i>/gi, '$1')\n\t\t.replace(/<s[^>]*>([\\s\\S]*?)<\\/s>/gi, '$1')\n\t\t.replace(/<del[^>]*>([\\s\\S]*?)<\\/del>/gi, '$1')\n\t\t.replace(/<a[^>]*>([\\s\\S]*?)<\\/a>/gi, '$1')\n\t\t.replace(/<p[^>]*>\\s*<br\\s*\\/?>\\s*<\\/p>/gi, '\\n')\n\t\t.replace(/<br\\s*\\/?>/gi, '\\n')\n\t\t.replace(/<\\/p>/gi, '\\n')\n\t\t.replace(/<\\/div>/gi, '\\n')\n\t\t.replace(/<\\/h[1-6]>/gi, '\\n')\n\t\t.replace(/<li[^>]*>/gi, '• ')\n\t\t.replace(/<\\/li>/gi, '\\n')\n\t\t.replace(/<[^>]+>/g, '')\n\t\t.replace(/&amp;/g, '&')\n\t\t.replace(/&lt;/g, '<')\n\t\t.replace(/&gt;/g, '>')\n\t\t.replace(/&nbsp;/g, ' ')\n\t\t.trim();\n}\n"],"names":["serializeNode","node","nodeType","Node","TEXT_NODE","textContent","_a","ELEMENT_NODE","el","tag","tagName","toLowerCase","inner","Array","from","childNodes","map","join","serializeChildren","length","_c","_b","firstChild","trimEnd","html","document","DOMParser","parseFromString","body","trim","replace","ssrFallback"],"mappings":"aA2BA,SAASA,EAAcC,aACtB,GAAIA,EAAKC,WAAaC,KAAKC,UAAW,OAAuB,UAAhBH,EAAKI,mBAAW,IAAAC,EAAAA,EAAI,GACjE,GAAIL,EAAKC,WAAaC,KAAKI,aAAc,MAAO,GAEhD,MAAMC,EAAKP,EACLQ,EAAMD,EAAGE,QAAQC,cACjBC,EA0DP,SAA2BJ,GAC1B,OAAOK,MAAMC,KAAKN,EAAGO,YAAYC,IAAIhB,GAAeiB,KAAK,GAC1D,CA5DeC,CAAkBV,GAEhC,OAAQC,GACP,IAAK,SACL,IAAK,IACJ,OAAOG,EAAQ,IAAIA,KAAW,GAG/B,IAAK,KACL,IAAK,IACL,IAAK,IACL,IAAK,MACL,IAAK,SAGL,IAAK,OACL,IAAK,MAGL,IAAK,IAuBL,IAAK,KACL,IAAK,KASL,IAAK,OACL,QACC,OAAOA,EA/BR,IAAK,KACJ,MAAO,KAER,IAAK,IACL,IAAK,MAIJ,OAF0B,IAAzBJ,EAAGO,WAAWI,QACyC,QAApB,QAAnCC,EAA0B,QAA1BC,EAACb,EAAGc,kBAAsB,IAAAD,OAAA,EAAAA,EAAEX,eAAO,IAAAU,OAAA,EAAAA,EAAET,eACjB,KAAOC,KAAWA,MAAY,KAGpD,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACJ,OAAOA,EAAQ,IAAIA,OAAa,KAMjC,IAAK,KACJ,WAAYA,EAAMW,cAEnB,IAAK,aACJ,OAAOX,EAAQ,KAMlB,+EA7EM,SAAyBY,GAC9B,IAAKA,EAAM,MAAO,GAElB,GAAwB,oBAAbC,SAA0B,CAEpC,OAAOzB,GADK,IAAI0B,WAAYC,gBAAgBH,EAAM,aACzBI,MAAMC,MAC/B,CAED,OA+ED,SAAqBL,GACpB,OAAOA,EACLM,QAAQ,sCAAuC,QAC/CA,QAAQ,4BAA6B,QACrCA,QAAQ,8BAA+B,MACvCA,QAAQ,4BAA6B,MACrCA,QAAQ,4BAA6B,MACrCA,QAAQ,gCAAiC,MACzCA,QAAQ,4BAA6B,MACrCA,QAAQ,kCAAmC,MAC3CA,QAAQ,eAAgB,MACxBA,QAAQ,UAAW,MACnBA,QAAQ,YAAa,MACrBA,QAAQ,eAAgB,MACxBA,QAAQ,cAAe,MACvBA,QAAQ,WAAY,MACpBA,QAAQ,WAAY,IACpBA,QAAQ,SAAU,KAClBA,QAAQ,QAAS,KACjBA,QAAQ,QAAS,KACjBA,QAAQ,UAAW,KACnBD,MACH,CArGQE,CAAYP,EACpB"}
@@ -1,2 +1,2 @@
1
- "use strict";function e(r){var n;if(r.nodeType===Node.TEXT_NODE)return null!==(n=r.textContent)&&void 0!==n?n:"";if(r.nodeType!==Node.ELEMENT_NODE)return"";const a=r,c=a.tagName.toLowerCase(),t=function(r){return Array.from(r.childNodes).map(e).join("")}(a);switch(c){case"strong":case"b":return t?`*${t}*`:"";case"em":case"i":return t?`_${t}_`:"";case"s":case"del":case"strike":return t?`~${t}~`:"";case"code":return t?`\`${t}\``:"";case"pre":return t?`\`\`\`${t}\`\`\``:"";case"a":case"ul":case"ol":case"body":default:return t;case"br":return"\n";case"p":case"div":return t?`${t}\n`:"\n";case"h1":case"h2":case"h3":case"h4":case"h5":case"h6":return t?`*${t}*\n`:"\n";case"li":return`• ${t.trimEnd()}\n`;case"blockquote":return t.split("\n").map((e=>e?`> ${e}`:"")).join("\n")+"\n"}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.toWhatsAppText=function(r){if(!r)return"";if("undefined"!=typeof document){return e((new DOMParser).parseFromString(r,"text/html").body).replace(/\n{3,}/g,"\n\n").trim()}return function(e){return e.replace(/<strong[^>]*>([\s\S]*?)<\/strong>/gi,"*$1*").replace(/<b[^>]*>([\s\S]*?)<\/b>/gi,"*$1*").replace(/<em[^>]*>([\s\S]*?)<\/em>/gi,"_$1_").replace(/<i[^>]*>([\s\S]*?)<\/i>/gi,"_$1_").replace(/<s[^>]*>([\s\S]*?)<\/s>/gi,"~$1~").replace(/<del[^>]*>([\s\S]*?)<\/del>/gi,"~$1~").replace(/<code[^>]*>([\s\S]*?)<\/code>/gi,"`$1`").replace(/<a[^>]*>([\s\S]*?)<\/a>/gi,"$1").replace(/<br\s*\/?>/gi,"\n").replace(/<\/p>/gi,"\n").replace(/<\/div>/gi,"\n").replace(/<\/h[1-6]>/gi,"\n").replace(/<li[^>]*>/gi,"• ").replace(/<\/li>/gi,"\n").replace(/<[^>]+>/g,"").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&nbsp;/g," ").replace(/\n{3,}/g,"\n\n").trim()}(r)};
1
+ "use strict";function e(r){var n,a,t;if(r.nodeType===Node.TEXT_NODE)return null!==(n=r.textContent)&&void 0!==n?n:"";if(r.nodeType!==Node.ELEMENT_NODE)return"";const s=r,c=s.tagName.toLowerCase(),i=function(r){return Array.from(r.childNodes).map(e).join("")}(s);switch(c){case"strong":case"b":return i?`*${i}*`:"";case"em":case"i":return i?`_${i}_`:"";case"s":case"del":case"strike":return i?`~${i}~`:"";case"code":return i?`\`${i}\``:"";case"pre":return i?`\`\`\`${i}\`\`\``:"";case"a":case"ul":case"ol":case"body":default:return i;case"br":return"\n";case"p":case"div":return 1===s.childNodes.length&&"br"===(null===(t=null===(a=s.firstChild)||void 0===a?void 0:a.tagName)||void 0===t?void 0:t.toLowerCase())?"\n":i?`${i}\n`:"\n";case"h1":case"h2":case"h3":case"h4":case"h5":case"h6":return i?`*${i}*\n`:"\n";case"li":return`• ${i.trimEnd()}\n`;case"blockquote":return i.split("\n").map((e=>e?`> ${e}`:"")).join("\n")+"\n"}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.toWhatsAppText=function(r){if(!r)return"";if("undefined"!=typeof document){return e((new DOMParser).parseFromString(r,"text/html").body).trim()}return function(e){return e.replace(/<strong[^>]*>([\s\S]*?)<\/strong>/gi,"*$1*").replace(/<b[^>]*>([\s\S]*?)<\/b>/gi,"*$1*").replace(/<em[^>]*>([\s\S]*?)<\/em>/gi,"_$1_").replace(/<i[^>]*>([\s\S]*?)<\/i>/gi,"_$1_").replace(/<s[^>]*>([\s\S]*?)<\/s>/gi,"~$1~").replace(/<del[^>]*>([\s\S]*?)<\/del>/gi,"~$1~").replace(/<code[^>]*>([\s\S]*?)<\/code>/gi,"`$1`").replace(/<a[^>]*>([\s\S]*?)<\/a>/gi,"$1").replace(/<p[^>]*>\s*<br\s*\/?>\s*<\/p>/gi,"\n").replace(/<br\s*\/?>/gi,"\n").replace(/<\/p>/gi,"\n").replace(/<\/div>/gi,"\n").replace(/<\/h[1-6]>/gi,"\n").replace(/<li[^>]*>/gi,"• ").replace(/<\/li>/gi,"\n").replace(/<[^>]+>/g,"").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&nbsp;/g," ").trim()}(r)};
2
2
  //# sourceMappingURL=toWhatsAppText.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"toWhatsAppText.js","sources":["../../../../src/editor/serializers/toWhatsAppText.ts"],"sourcesContent":["/**\n * Converts TipTap HTML to WhatsApp-flavoured markdown text.\n *\n * WhatsApp formatting:\n * *bold* _italic_ ~strikethrough~ ```monospace```\n *\n * Links: WhatsApp does not support hyperlinks.\n * <a href=\"https://…\">Visit us</a> → Visit us (display text kept, href dropped)\n *\n * @example\n * const { html } = ref.current?.getContent();\n * const waText = toWhatsAppText(html);\n * sendWhatsApp({ text: waText });\n */\nexport function toWhatsAppText(html: string): string {\n\tif (!html) return '';\n\n\tif (typeof document !== 'undefined') {\n\t\tconst doc = new DOMParser().parseFromString(html, 'text/html');\n\t\treturn serializeNode(doc.body)\n\t\t\t.replace(/\\n{3,}/g, '\\n\\n')\n\t\t\t.trim();\n\t}\n\n\t// SSR / Node.js fallback — handles simple non-nested markup\n\treturn ssrFallback(html);\n}\n\n// ---------------------------------------------------------------------------\n// Browser path — DOM-based, handles nested marks correctly\n// ---------------------------------------------------------------------------\n\nfunction serializeNode(node: Node): string {\n\tif (node.nodeType === Node.TEXT_NODE) {\n\t\treturn node.textContent ?? '';\n\t}\n\tif (node.nodeType !== Node.ELEMENT_NODE) return '';\n\n\tconst el = node as Element;\n\tconst tag = el.tagName.toLowerCase();\n\tconst inner = serializeChildren(el);\n\n\tswitch (tag) {\n\t\tcase 'strong':\n\t\tcase 'b':\n\t\t\treturn inner ? `*${inner}*` : '';\n\n\t\tcase 'em':\n\t\tcase 'i':\n\t\t\treturn inner ? `_${inner}_` : '';\n\n\t\tcase 's':\n\t\tcase 'del':\n\t\tcase 'strike':\n\t\t\treturn inner ? `~${inner}~` : '';\n\n\t\tcase 'code':\n\t\t\treturn inner ? `\\`${inner}\\`` : '';\n\n\t\tcase 'pre':\n\t\t\treturn inner ? `\\`\\`\\`${inner}\\`\\`\\`` : '';\n\n\t\tcase 'a':\n\t\t\treturn inner;\n\n\t\tcase 'br':\n\t\t\treturn '\\n';\n\n\t\tcase 'p':\n\t\tcase 'div':\n\t\t\treturn inner ? `${inner}\\n` : '\\n';\n\n\t\tcase 'h1':\n\t\tcase 'h2':\n\t\tcase 'h3':\n\t\tcase 'h4':\n\t\tcase 'h5':\n\t\tcase 'h6':\n\t\t\treturn inner ? `*${inner}*\\n` : '\\n';\n\n\t\tcase 'ul':\n\t\tcase 'ol':\n\t\t\treturn inner;\n\n\t\tcase 'li':\n\t\t\treturn `• ${inner.trimEnd()}\\n`;\n\n\t\tcase 'blockquote':\n\t\t\treturn (\n\t\t\t\tinner\n\t\t\t\t\t.split('\\n')\n\t\t\t\t\t.map((l) => (l ? `> ${l}` : ''))\n\t\t\t\t\t.join('\\n') + '\\n'\n\t\t\t);\n\n\t\tcase 'body':\n\t\tdefault:\n\t\t\treturn inner;\n\t}\n}\n\nfunction serializeChildren(el: Element): string {\n\treturn Array.from(el.childNodes).map(serializeNode).join('');\n}\n\n// ---------------------------------------------------------------------------\n// SSR fallback — regex-based, best-effort for simple markup\n// ---------------------------------------------------------------------------\n\nfunction ssrFallback(html: string): string {\n\treturn html\n\t\t.replace(/<strong[^>]*>([\\s\\S]*?)<\\/strong>/gi, '*$1*')\n\t\t.replace(/<b[^>]*>([\\s\\S]*?)<\\/b>/gi, '*$1*')\n\t\t.replace(/<em[^>]*>([\\s\\S]*?)<\\/em>/gi, '_$1_')\n\t\t.replace(/<i[^>]*>([\\s\\S]*?)<\\/i>/gi, '_$1_')\n\t\t.replace(/<s[^>]*>([\\s\\S]*?)<\\/s>/gi, '~$1~')\n\t\t.replace(/<del[^>]*>([\\s\\S]*?)<\\/del>/gi, '~$1~')\n\t\t.replace(/<code[^>]*>([\\s\\S]*?)<\\/code>/gi, '`$1`')\n\t\t.replace(/<a[^>]*>([\\s\\S]*?)<\\/a>/gi, '$1')\n\t\t.replace(/<br\\s*\\/?>/gi, '\\n')\n\t\t.replace(/<\\/p>/gi, '\\n')\n\t\t.replace(/<\\/div>/gi, '\\n')\n\t\t.replace(/<\\/h[1-6]>/gi, '\\n')\n\t\t.replace(/<li[^>]*>/gi, '• ')\n\t\t.replace(/<\\/li>/gi, '\\n')\n\t\t.replace(/<[^>]+>/g, '')\n\t\t.replace(/&amp;/g, '&')\n\t\t.replace(/&lt;/g, '<')\n\t\t.replace(/&gt;/g, '>')\n\t\t.replace(/&nbsp;/g, ' ')\n\t\t.replace(/\\n{3,}/g, '\\n\\n')\n\t\t.trim();\n}\n"],"names":["serializeNode","node","nodeType","Node","TEXT_NODE","textContent","_a","ELEMENT_NODE","el","tag","tagName","toLowerCase","inner","Array","from","childNodes","map","join","serializeChildren","trimEnd","split","l","html","document","DOMParser","parseFromString","body","replace","trim","ssrFallback"],"mappings":"aAgCA,SAASA,EAAcC,SACtB,GAAIA,EAAKC,WAAaC,KAAKC,UAC1B,OAAuB,UAAhBH,EAAKI,mBAAW,IAAAC,EAAAA,EAAI,GAE5B,GAAIL,EAAKC,WAAaC,KAAKI,aAAc,MAAO,GAEhD,MAAMC,EAAKP,EACLQ,EAAMD,EAAGE,QAAQC,cACjBC,EA6DP,SAA2BJ,GAC1B,OAAOK,MAAMC,KAAKN,EAAGO,YAAYC,IAAIhB,GAAeiB,KAAK,GAC1D,CA/DeC,CAAkBV,GAEhC,OAAQC,GACP,IAAK,SACL,IAAK,IACJ,OAAOG,EAAQ,IAAIA,KAAW,GAE/B,IAAK,KACL,IAAK,IACJ,OAAOA,EAAQ,IAAIA,KAAW,GAE/B,IAAK,IACL,IAAK,MACL,IAAK,SACJ,OAAOA,EAAQ,IAAIA,KAAW,GAE/B,IAAK,OACJ,OAAOA,EAAQ,KAAKA,MAAY,GAEjC,IAAK,MACJ,OAAOA,EAAQ,SAASA,UAAgB,GAEzC,IAAK,IAkBL,IAAK,KACL,IAAK,KAcL,IAAK,OACL,QACC,OAAOA,EAhCR,IAAK,KACJ,MAAO,KAER,IAAK,IACL,IAAK,MACJ,OAAOA,EAAQ,GAAGA,MAAY,KAE/B,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACJ,OAAOA,EAAQ,IAAIA,OAAa,KAMjC,IAAK,KACJ,WAAYA,EAAMO,cAEnB,IAAK,aACJ,OACCP,EACEQ,MAAM,MACNJ,KAAKK,GAAOA,EAAI,KAAKA,IAAM,KAC3BJ,KAAK,MAAQ,KAOnB,+EArFM,SAAyBK,GAC9B,IAAKA,EAAM,MAAO,GAElB,GAAwB,oBAAbC,SAA0B,CAEpC,OAAOvB,GADK,IAAIwB,WAAYC,gBAAgBH,EAAM,aACzBI,MACvBC,QAAQ,UAAW,QACnBC,MACF,CAGD,OAoFD,SAAqBN,GACpB,OAAOA,EACLK,QAAQ,sCAAuC,QAC/CA,QAAQ,4BAA6B,QACrCA,QAAQ,8BAA+B,QACvCA,QAAQ,4BAA6B,QACrCA,QAAQ,4BAA6B,QACrCA,QAAQ,gCAAiC,QACzCA,QAAQ,kCAAmC,QAC3CA,QAAQ,4BAA6B,MACrCA,QAAQ,eAAgB,MACxBA,QAAQ,UAAW,MACnBA,QAAQ,YAAa,MACrBA,QAAQ,eAAgB,MACxBA,QAAQ,cAAe,MACvBA,QAAQ,WAAY,MACpBA,QAAQ,WAAY,IACpBA,QAAQ,SAAU,KAClBA,QAAQ,QAAS,KACjBA,QAAQ,QAAS,KACjBA,QAAQ,UAAW,KACnBA,QAAQ,UAAW,QACnBC,MACH,CA3GQC,CAAYP,EACpB"}
1
+ {"version":3,"file":"toWhatsAppText.js","sources":["../../../../src/editor/serializers/toWhatsAppText.ts"],"sourcesContent":["/**\n * Converts TipTap HTML to WhatsApp-flavoured markdown text.\n *\n * WhatsApp formatting:\n * *bold* _italic_ ~strikethrough~ ```monospace```\n *\n * Links: WhatsApp does not support hyperlinks.\n * <a href=\"https://…\">Visit us</a> → Visit us (display text kept, href dropped)\n *\n * @example\n * const { html } = ref.current?.getContent();\n * const waText = toWhatsAppText(html);\n * sendWhatsApp({ text: waText });\n */\nexport function toWhatsAppText(html: string): string {\n\tif (!html) return '';\n\n\tif (typeof document !== 'undefined') {\n\t\tconst doc = new DOMParser().parseFromString(html, 'text/html');\n\t\treturn serializeNode(doc.body).trim();\n\t}\n\n\t// SSR / Node.js fallback — handles simple non-nested markup\n\treturn ssrFallback(html);\n}\n\n// ---------------------------------------------------------------------------\n// Browser path — DOM-based, handles nested marks correctly\n// ---------------------------------------------------------------------------\n\nfunction serializeNode(node: Node): string {\n\tif (node.nodeType === Node.TEXT_NODE) {\n\t\treturn node.textContent ?? '';\n\t}\n\tif (node.nodeType !== Node.ELEMENT_NODE) return '';\n\n\tconst el = node as Element;\n\tconst tag = el.tagName.toLowerCase();\n\tconst inner = serializeChildren(el);\n\n\tswitch (tag) {\n\t\tcase 'strong':\n\t\tcase 'b':\n\t\t\treturn inner ? `*${inner}*` : '';\n\n\t\tcase 'em':\n\t\tcase 'i':\n\t\t\treturn inner ? `_${inner}_` : '';\n\n\t\tcase 's':\n\t\tcase 'del':\n\t\tcase 'strike':\n\t\t\treturn inner ? `~${inner}~` : '';\n\n\t\tcase 'code':\n\t\t\treturn inner ? `\\`${inner}\\`` : '';\n\n\t\tcase 'pre':\n\t\t\treturn inner ? `\\`\\`\\`${inner}\\`\\`\\`` : '';\n\n\t\tcase 'a':\n\t\t\treturn inner;\n\n\t\tcase 'br':\n\t\t\treturn '\\n';\n\n\t\tcase 'p':\n\t\tcase 'div': {\n\t\t\tconst isBlankLine =\n\t\t\t\tel.childNodes.length === 1 &&\n\t\t\t\t(el.firstChild as Element)?.tagName?.toLowerCase() === 'br';\n\t\t\treturn isBlankLine ? '\\n' : inner ? `${inner}\\n` : '\\n';\n\t\t}\n\n\t\tcase 'h1':\n\t\tcase 'h2':\n\t\tcase 'h3':\n\t\tcase 'h4':\n\t\tcase 'h5':\n\t\tcase 'h6':\n\t\t\treturn inner ? `*${inner}*\\n` : '\\n';\n\n\t\tcase 'ul':\n\t\tcase 'ol':\n\t\t\treturn inner;\n\n\t\tcase 'li':\n\t\t\treturn `• ${inner.trimEnd()}\\n`;\n\n\t\tcase 'blockquote':\n\t\t\treturn (\n\t\t\t\tinner\n\t\t\t\t\t.split('\\n')\n\t\t\t\t\t.map((l) => (l ? `> ${l}` : ''))\n\t\t\t\t\t.join('\\n') + '\\n'\n\t\t\t);\n\n\t\tcase 'body':\n\t\tdefault:\n\t\t\treturn inner;\n\t}\n}\n\nfunction serializeChildren(el: Element): string {\n\treturn Array.from(el.childNodes).map(serializeNode).join('');\n}\n\n// ---------------------------------------------------------------------------\n// SSR fallback — regex-based, best-effort for simple markup\n// ---------------------------------------------------------------------------\n\nfunction ssrFallback(html: string): string {\n\treturn html\n\t\t.replace(/<strong[^>]*>([\\s\\S]*?)<\\/strong>/gi, '*$1*')\n\t\t.replace(/<b[^>]*>([\\s\\S]*?)<\\/b>/gi, '*$1*')\n\t\t.replace(/<em[^>]*>([\\s\\S]*?)<\\/em>/gi, '_$1_')\n\t\t.replace(/<i[^>]*>([\\s\\S]*?)<\\/i>/gi, '_$1_')\n\t\t.replace(/<s[^>]*>([\\s\\S]*?)<\\/s>/gi, '~$1~')\n\t\t.replace(/<del[^>]*>([\\s\\S]*?)<\\/del>/gi, '~$1~')\n\t\t.replace(/<code[^>]*>([\\s\\S]*?)<\\/code>/gi, '`$1`')\n\t\t.replace(/<a[^>]*>([\\s\\S]*?)<\\/a>/gi, '$1')\n\t\t.replace(/<p[^>]*>\\s*<br\\s*\\/?>\\s*<\\/p>/gi, '\\n')\n\t\t.replace(/<br\\s*\\/?>/gi, '\\n')\n\t\t.replace(/<\\/p>/gi, '\\n')\n\t\t.replace(/<\\/div>/gi, '\\n')\n\t\t.replace(/<\\/h[1-6]>/gi, '\\n')\n\t\t.replace(/<li[^>]*>/gi, '• ')\n\t\t.replace(/<\\/li>/gi, '\\n')\n\t\t.replace(/<[^>]+>/g, '')\n\t\t.replace(/&amp;/g, '&')\n\t\t.replace(/&lt;/g, '<')\n\t\t.replace(/&gt;/g, '>')\n\t\t.replace(/&nbsp;/g, ' ')\n\t\t.trim();\n}\n"],"names":["serializeNode","node","nodeType","Node","TEXT_NODE","textContent","_a","ELEMENT_NODE","el","tag","tagName","toLowerCase","inner","Array","from","childNodes","map","join","serializeChildren","length","_c","_b","firstChild","trimEnd","split","l","html","document","DOMParser","parseFromString","body","trim","replace","ssrFallback"],"mappings":"aA8BA,SAASA,EAAcC,aACtB,GAAIA,EAAKC,WAAaC,KAAKC,UAC1B,OAAuB,UAAhBH,EAAKI,mBAAW,IAAAC,EAAAA,EAAI,GAE5B,GAAIL,EAAKC,WAAaC,KAAKI,aAAc,MAAO,GAEhD,MAAMC,EAAKP,EACLQ,EAAMD,EAAGE,QAAQC,cACjBC,EAiEP,SAA2BJ,GAC1B,OAAOK,MAAMC,KAAKN,EAAGO,YAAYC,IAAIhB,GAAeiB,KAAK,GAC1D,CAnEeC,CAAkBV,GAEhC,OAAQC,GACP,IAAK,SACL,IAAK,IACJ,OAAOG,EAAQ,IAAIA,KAAW,GAE/B,IAAK,KACL,IAAK,IACJ,OAAOA,EAAQ,IAAIA,KAAW,GAE/B,IAAK,IACL,IAAK,MACL,IAAK,SACJ,OAAOA,EAAQ,IAAIA,KAAW,GAE/B,IAAK,OACJ,OAAOA,EAAQ,KAAKA,MAAY,GAEjC,IAAK,MACJ,OAAOA,EAAQ,SAASA,UAAgB,GAEzC,IAAK,IAsBL,IAAK,KACL,IAAK,KAcL,IAAK,OACL,QACC,OAAOA,EApCR,IAAK,KACJ,MAAO,KAER,IAAK,IACL,IAAK,MAIJ,OAF0B,IAAzBJ,EAAGO,WAAWI,QACyC,QAApB,QAAnCC,EAA0B,QAA1BC,EAACb,EAAGc,kBAAsB,IAAAD,OAAA,EAAAA,EAAEX,eAAO,IAAAU,OAAA,EAAAA,EAAET,eACjB,KAAOC,KAAWA,MAAY,KAGpD,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACJ,OAAOA,EAAQ,IAAIA,OAAa,KAMjC,IAAK,KACJ,WAAYA,EAAMW,cAEnB,IAAK,aACJ,OACCX,EACEY,MAAM,MACNR,KAAKS,GAAOA,EAAI,KAAKA,IAAM,KAC3BR,KAAK,MAAQ,KAOnB,+EAvFM,SAAyBS,GAC9B,IAAKA,EAAM,MAAO,GAElB,GAAwB,oBAAbC,SAA0B,CAEpC,OAAO3B,GADK,IAAI4B,WAAYC,gBAAgBH,EAAM,aACzBI,MAAMC,MAC/B,CAGD,OAwFD,SAAqBL,GACpB,OAAOA,EACLM,QAAQ,sCAAuC,QAC/CA,QAAQ,4BAA6B,QACrCA,QAAQ,8BAA+B,QACvCA,QAAQ,4BAA6B,QACrCA,QAAQ,4BAA6B,QACrCA,QAAQ,gCAAiC,QACzCA,QAAQ,kCAAmC,QAC3CA,QAAQ,4BAA6B,MACrCA,QAAQ,kCAAmC,MAC3CA,QAAQ,eAAgB,MACxBA,QAAQ,UAAW,MACnBA,QAAQ,YAAa,MACrBA,QAAQ,eAAgB,MACxBA,QAAQ,cAAe,MACvBA,QAAQ,WAAY,MACpBA,QAAQ,WAAY,IACpBA,QAAQ,SAAU,KAClBA,QAAQ,QAAS,KACjBA,QAAQ,QAAS,KACjBA,QAAQ,UAAW,KACnBD,MACH,CA/GQE,CAAYP,EACpB"}
@@ -1,3 +1,4 @@
1
+ /// <reference types="react" />
1
2
  export declare const Menus: ({
2
3
  displayName: string;
3
4
  key: number;
@@ -1 +1 @@
1
- {"version":3,"file":"FeatureAnnouncementProvider.js","sources":["../../../../src/components/feature-announcements/FeatureAnnouncementProvider.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useState } from 'react';\nimport Joyride, { ACTIONS } from 'react-joyride';\nimport { SELECTORS } from './constants';\nimport { useFeatureAnnouncements } from './hooks';\nimport MajorUpdatePopup from './MajorUpdatePopup';\nimport MinorUpdatePopup from './MinorUpdatePopup';\nimport { FeatureAnnouncement, FeatureAnnouncementProviderProps } from './types';\nimport { VideoModal } from './VideoModal';\n\nconst FeatureAnnouncementProvider: React.FC<\n\tFeatureAnnouncementProviderProps\n> = ({\n\tchildren,\n\tfetchVisibleFeatures,\n\tgetStoreFeatureProgress,\n\tfetchFeatureById,\n\tmarkFeatureAsViewedForStore,\n\tisFeatureApplicableToCurrentPage,\n\tmodule,\n\trouter,\n\tstoreId,\n\tonAnnouncementShown,\n\tonAnnouncementInteracted,\n}) => {\n\tconst {\n\t\tmajorUpdateFeatures,\n\t\tminorUpdateFeatures,\n\t\tisLoading,\n\t\tmarkFeatureAsViewed,\n\t} = useFeatureAnnouncements({\n\t\tfetchVisibleFeatures,\n\t\tgetStoreFeatureProgress,\n\t\tfetchFeatureById,\n\t\tmarkFeatureAsViewedForStore,\n\t\tisFeatureApplicableToCurrentPage,\n\t\tmodule,\n\t\trouter,\n\t});\n\n\tconst [currentMajorFeature, setCurrentMajorFeature] =\n\t\tuseState<FeatureAnnouncement | null>(null);\n\tconst [currentMinorFeature, setCurrentMinorFeature] =\n\t\tuseState<FeatureAnnouncement | null>(null);\n\tconst [runJoyride, setRunJoyride] = useState(false);\n\tconst [joyrideSteps, setJoyrideSteps] = useState<any[]>([]);\n\tconst [runMajorJoyride, setRunMajorJoyride] = useState(false);\n\tconst [majorJoyrideSteps, setMajorJoyrideSteps] = useState<any[]>([]);\n\tconst [isProcessingMajorUpdate, setIsProcessingMajorUpdate] = useState(false);\n\tconst [isProcessingMinorUpdate, setIsProcessingMinorUpdate] = useState(false);\n\tconst [availableMinorFeatures, setAvailableMinorFeatures] = useState<\n\t\tFeatureAnnouncement[]\n\t>([]);\n\tconst [minorFeaturesSkipped, setMinorFeaturesSkipped] = useState(false);\n\tconst [showMinorUpdates, setShowMinorUpdates] = useState(false);\n\tconst [isVideoModalOpen, setIsVideoModalOpen] = useState(false);\n\tconst [videoUrl, setVideoUrl] = useState('');\n\tconst [blockPopups, setBlockPopups] = useState(false);\n\tconst [isClosingMajor, setIsClosingMajor] = useState(false);\n\tconst [isClosingMinor, setIsClosingMinor] = useState(false);\n\tconst [majorJoyrideKey, setMajorJoyrideKey] = useState(0);\n\tconst [minorJoyrideKey, setMinorJoyrideKey] = useState(0);\n\tconst [shownMinorFeatureIds, setShownMinorFeatureIds] = useState<Set<string>>(\n\t\tnew Set(),\n\t);\n\n\t// Add custom style for spotlight cutout effect\n\tuseEffect(() => {\n\t\tconst styleId = 'minor-spotlight-cutout-style';\n\t\tlet styleElement = document.getElementById(styleId) as HTMLStyleElement;\n\n\t\tif (!styleElement) {\n\t\t\tstyleElement = document.createElement('style');\n\t\t\tstyleElement.id = styleId;\n\t\t\tdocument.head.appendChild(styleElement);\n\t\t}\n\n\t\tstyleElement.textContent = `\n\t\t\t.react-joyride__spotlight {\n\t\t\t\ttransition: box-shadow 0.3s ease-in-out !important;\n\t\t\t\twill-change: box-shadow, transform;\n\t\t\t\ttransform: translateZ(0);\n\t\t\t}\n\t\t\t.react-joyride__tooltip {\n\t\t\t\twill-change: transform, opacity;\n\t\t\t\ttransform: translateZ(0);\n\t\t\t}\n\t\t\t.react-joyride__floater {\n\t\t\t\tright: 12px !important;\n\t\t\t\tleft: auto !important;\n\t\t\t}\n\t\t`;\n\n\t\treturn () => {\n\t\t\tconst el = document.getElementById(styleId);\n\t\t\tif (el) {\n\t\t\t\tel.remove();\n\t\t\t}\n\t\t};\n\t}, []);\n\n\t// Force Joyride remount on navigation to prevent stale state\n\tuseEffect(() => {\n\t\tsetMajorJoyrideKey((prev) => prev + 1);\n\t\tsetMinorJoyrideKey((prev) => prev + 1);\n\t\tsetIsClosingMajor(false);\n\t\tsetIsClosingMinor(false);\n\t\t// Reset session tracking on navigation to allow features to show on new pages\n\t\tsetShownMinorFeatureIds(new Set());\n\t}, [router?.pathname]);\n\n\tuseEffect(() => {\n\t\tif (\n\t\t\tmajorUpdateFeatures.length > 0 &&\n\t\t\t!currentMajorFeature &&\n\t\t\t!isLoading &&\n\t\t\t!isProcessingMajorUpdate &&\n\t\t\t!blockPopups\n\t\t) {\n\t\t\tsetShowMinorUpdates(false);\n\t\t\tsetMinorFeaturesSkipped(false);\n\t\t\tsetRunJoyride(false);\n\t\t\tsetJoyrideSteps([]);\n\t\t\tsetCurrentMinorFeature(null);\n\t\t\tsetAvailableMinorFeatures([]);\n\n\t\t\tlet attempts = 0;\n\t\t\tconst MAX_ATTEMPTS = 10;\n\n\t\t\tconst checkWhatsNewButton = () => {\n\t\t\t\tattempts++;\n\t\t\t\tconst whatsNewButton = document.querySelector(\n\t\t\t\t\t'[data-testid=\"whats-new-button\"]',\n\t\t\t\t);\n\n\t\t\t\tif (whatsNewButton) {\n\t\t\t\t\tshowMajorUpdateJoyride(majorUpdateFeatures[0]);\n\t\t\t\t} else if (attempts < MAX_ATTEMPTS) {\n\t\t\t\t\tsetTimeout(checkWhatsNewButton, 1000);\n\t\t\t\t} else {\n\t\t\t\t\tsetShowMinorUpdates(true);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tcheckWhatsNewButton();\n\t\t} else if (majorUpdateFeatures.length === 0 && !isLoading) {\n\t\t\tsetShowMinorUpdates(true);\n\t\t}\n\t}, [\n\t\tmajorUpdateFeatures,\n\t\tcurrentMajorFeature,\n\t\tisLoading,\n\t\tisProcessingMajorUpdate,\n\t\tblockPopups,\n\t]);\n\n\tuseEffect(() => {\n\t\t// Only run this special logic if a feature is being forced via URL\n\t\tconst featureIdFromQuery = router?.query?.['featureId'] as string;\n\n\t\tif (!featureIdFromQuery || isLoading || minorUpdateFeatures.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst forcedFeature = minorUpdateFeatures.find(\n\t\t\t(f) => f.id === featureIdFromQuery,\n\t\t);\n\n\t\tif (!forcedFeature || !forcedFeature.featureTag) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Prevent the standard flow from interfering\n\t\tsetMinorFeaturesSkipped(true);\n\t\t// Mark that we're processing to prevent other effects from interfering\n\t\tsetIsProcessingMinorUpdate(true);\n\n\t\tlet attempts = 0;\n\t\tconst maxAttempts = 25; // 5 seconds\n\t\tconst interval = setInterval(() => {\n\t\t\tattempts++;\n\t\t\tconst targetSelector =\n\t\t\t\tforcedFeature.featureTag.startsWith('#') ||\n\t\t\t\tforcedFeature.featureTag.startsWith('.') ||\n\t\t\t\tforcedFeature.featureTag.startsWith('[')\n\t\t\t\t\t? forcedFeature.featureTag\n\t\t\t\t\t: `#${forcedFeature.featureTag}`;\n\n\t\t\tconst element = document.querySelector(targetSelector);\n\n\t\t\tif (element) {\n\t\t\t\t// In test mode, pass the feature array directly to avoid async state issues\n\t\t\t\tconst testModeFeatures = [forcedFeature];\n\t\t\t\tsetAvailableMinorFeatures(testModeFeatures);\n\t\t\t\tshowMinorUpdateJoyride(forcedFeature, testModeFeatures);\n\t\t\t\t// Don't reset processing flag here - let user interaction handle it\n\t\t\t\t// This prevents auto-closing when multiple popups exist or when scrolling\n\t\t\t\tclearInterval(interval);\n\t\t\t} else if (attempts >= maxAttempts) {\n\t\t\t\t// Fallback for safety, though user expects it to be there.\n\t\t\t\t// We could log an error here.\n\t\t\t\t// Only reset on timeout (element not found)\n\t\t\t\tsetIsProcessingMinorUpdate(false);\n\t\t\t\tclearInterval(interval);\n\t\t\t}\n\t\t}, 200);\n\n\t\treturn () => {\n\t\t\tclearInterval(interval);\n\t\t\t// Don't reset processing flag on cleanup - it causes premature popup closure\n\t\t\t// The flag will be managed by user interactions (skip/explore handlers)\n\t\t};\n\t}, [minorUpdateFeatures, router?.query?.['featureId'], isLoading]);\n\n\tuseEffect(() => {\n\t\tif (\n\t\t\tminorUpdateFeatures.length > 0 &&\n\t\t\t!isLoading &&\n\t\t\t!runJoyride &&\n\t\t\t!isProcessingMinorUpdate &&\n\t\t\t!currentMinorFeature &&\n\t\t\t!minorFeaturesSkipped &&\n\t\t\tshowMinorUpdates &&\n\t\t\t!blockPopups\n\t\t) {\n\t\t\tlet observer: MutationObserver | null = null;\n\t\t\tlet scrollListener: (() => void) | null = null;\n\t\t\tlet checkTimeout: ReturnType<typeof setTimeout> | null = null;\n\t\t\tlet isCleanedUp = false;\n\n\t\t\tconst checkElementsAndStartTour = () => {\n\t\t\t\tif (\n\t\t\t\t\tisCleanedUp ||\n\t\t\t\t\tisProcessingMinorUpdate ||\n\t\t\t\t\tcurrentMinorFeature ||\n\t\t\t\t\tminorFeaturesSkipped ||\n\t\t\t\t\t!showMinorUpdates\n\t\t\t\t)\n\t\t\t\t\treturn;\n\n\t\t\t\tconst availableFeatures = minorUpdateFeatures.filter((feature) => {\n\t\t\t\t\tif (!feature.featureTag || feature.featureTag.trim() === '') {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Skip features already shown in this session\n\t\t\t\t\tif (shownMinorFeatureIds.has(feature.id)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst targetSelector =\n\t\t\t\t\t\tfeature.featureTag.startsWith('#') ||\n\t\t\t\t\t\tfeature.featureTag.startsWith('.') ||\n\t\t\t\t\t\tfeature.featureTag.startsWith('[')\n\t\t\t\t\t\t\t? feature.featureTag\n\t\t\t\t\t\t\t: `#${feature.featureTag}`;\n\n\t\t\t\t\tconst element = document.querySelector(targetSelector);\n\t\t\t\t\treturn element !== null;\n\t\t\t\t});\n\n\t\t\t\tif (availableFeatures.length > 0) {\n\t\t\t\t\tsetAvailableMinorFeatures(availableFeatures);\n\t\t\t\t\t// Pass features directly to avoid async state issues\n\t\t\t\t\tshowMinorUpdateJoyride(availableFeatures[0], availableFeatures);\n\n\t\t\t\t\tif (observer) {\n\t\t\t\t\t\tobserver.disconnect();\n\t\t\t\t\t\tobserver = null;\n\t\t\t\t\t}\n\t\t\t\t\tif (scrollListener) {\n\t\t\t\t\t\twindow.removeEventListener('scroll', scrollListener);\n\t\t\t\t\t\tscrollListener = null;\n\t\t\t\t\t}\n\t\t\t\t\tif (checkTimeout) {\n\t\t\t\t\t\tclearTimeout(checkTimeout);\n\t\t\t\t\t\tcheckTimeout = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tobserver = new MutationObserver((mutations) => {\n\t\t\t\tlet shouldCheck = false;\n\t\t\t\tfor (const mutation of mutations) {\n\t\t\t\t\tif (mutation.type === 'childList' && mutation.addedNodes.length > 0) {\n\t\t\t\t\t\tfor (let i = 0; i < mutation.addedNodes.length; i++) {\n\t\t\t\t\t\t\tconst node = mutation.addedNodes[i];\n\t\t\t\t\t\t\tif (node.nodeType === Node.ELEMENT_NODE) {\n\t\t\t\t\t\t\t\tconst element = node as Element;\n\t\t\t\t\t\t\t\tif (element.id || element.querySelector('[id]')) {\n\t\t\t\t\t\t\t\t\tshouldCheck = true;\n\t\t\t\t\t\t\t\t\tbreak;\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}\n\t\t\t\t\tif (shouldCheck) break;\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\t!runJoyride &&\n\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\tshowMinorUpdates &&\n\t\t\t\t\tshouldCheck\n\t\t\t\t) {\n\t\t\t\t\tif (checkTimeout) {\n\t\t\t\t\t\tclearTimeout(checkTimeout);\n\t\t\t\t\t}\n\t\t\t\t\tcheckTimeout = setTimeout(() => {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\t\t\tshowMinorUpdates\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tcheckElementsAndStartTour();\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 200);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tscrollListener = () => {\n\t\t\t\tif (\n\t\t\t\t\t!runJoyride &&\n\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\tshowMinorUpdates\n\t\t\t\t) {\n\t\t\t\t\tif (checkTimeout) {\n\t\t\t\t\t\tclearTimeout(checkTimeout);\n\t\t\t\t\t}\n\t\t\t\t\t// Use RAF for smoother performance synced with browser paint\n\t\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\t\tcheckTimeout = setTimeout(() => {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\t\t\t\tshowMinorUpdates\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tcheckElementsAndStartTour();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, 300);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif (observer) {\n\t\t\t\tobserver.observe(document.body, {\n\t\t\t\t\tchildList: true,\n\t\t\t\t\tsubtree: true,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (scrollListener) {\n\t\t\t\twindow.addEventListener('scroll', scrollListener, { passive: true });\n\t\t\t}\n\n\t\t\tcheckElementsAndStartTour();\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (\n\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\tshowMinorUpdates\n\t\t\t\t) {\n\t\t\t\t\tcheckElementsAndStartTour();\n\t\t\t\t}\n\t\t\t}, 100);\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (\n\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\tshowMinorUpdates\n\t\t\t\t) {\n\t\t\t\t\tcheckElementsAndStartTour();\n\t\t\t\t}\n\t\t\t}, 1000);\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (\n\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\tshowMinorUpdates\n\t\t\t\t) {\n\t\t\t\t\tcheckElementsAndStartTour();\n\t\t\t\t}\n\t\t\t}, 500);\n\n\t\t\treturn () => {\n\t\t\t\tisCleanedUp = true;\n\t\t\t\tif (observer) {\n\t\t\t\t\tobserver.disconnect();\n\t\t\t\t}\n\t\t\t\tif (scrollListener) {\n\t\t\t\t\twindow.removeEventListener('scroll', scrollListener);\n\t\t\t\t}\n\t\t\t\tif (checkTimeout) {\n\t\t\t\t\tclearTimeout(checkTimeout);\n\t\t\t\t}\n\t\t\t};\n\t\t} else if (minorUpdateFeatures.length === 0 || isLoading) {\n\t\t\t// Don't clear joyride if we're in test mode with an active feature\n\t\t\tconst featureIdFromQuery = router?.query?.['featureId'] as string;\n\t\t\tconst isTestModeWithActiveFeature =\n\t\t\t\tfeatureIdFromQuery && currentMinorFeature;\n\n\t\t\tif (!isTestModeWithActiveFeature) {\n\t\t\t\tsetRunJoyride(false);\n\t\t\t\tsetJoyrideSteps([]);\n\t\t\t\tsetCurrentMinorFeature(null);\n\t\t\t\tsetAvailableMinorFeatures([]);\n\t\t\t\tsetMinorFeaturesSkipped(false);\n\t\t\t}\n\t\t}\n\t}, [\n\t\tminorUpdateFeatures,\n\t\tisLoading,\n\t\trunJoyride,\n\t\tisProcessingMinorUpdate,\n\t\tcurrentMinorFeature,\n\t\tminorFeaturesSkipped,\n\t\tshowMinorUpdates,\n\t\tmarkFeatureAsViewed,\n\t\tblockPopups,\n\t]);\n\n\tconst showMajorUpdateJoyride = (feature) => {\n\t\tsetCurrentMajorFeature(feature);\n\n\t\tconst currentIndex = majorUpdateFeatures.findIndex(\n\t\t\t(f) => f.id === feature.id,\n\t\t);\n\t\tconst totalFeatures = majorUpdateFeatures.length;\n\n\t\tconst majorSteps = [\n\t\t\t{\n\t\t\t\ttarget: SELECTORS.WHATS_NEW_BUTTON,\n\t\t\t\tcontent: (\n\t\t\t\t\t<MajorUpdatePopup\n\t\t\t\t\t\tfeature={feature}\n\t\t\t\t\t\tcurrentIndex={currentIndex}\n\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\tonSkip={() => handleSkipMajorUpdate(feature)}\n\t\t\t\t\t\tonExplore={(triggeredAction) => handleExploreFeature(feature, triggeredAction)}\n\t\t\t\t\t\tonPrevious={() => handlePreviousMajorUpdate(feature)}\n\t\t\t\t\t\tonNext={() => handleNextMajorUpdate(feature)}\n\t\t\t\t\t\tsetIsClosing={setIsClosingMajor}\n\t\t\t\t\t/>\n\t\t\t\t),\n\t\t\t\tplacement: 'bottom-start',\n\t\t\t\tplacementBeacon: 'top-end',\n\t\t\t\tdisableBeacon: true,\n\t\t\t\thideCloseButton: true,\n\t\t\t\thideSkipButton: true,\n\t\t\t\thideFooter: true,\n\t\t\t\toffset: 0,\n\t\t\t\tdata: { feature, isMajor: true },\n\t\t\t\tstyles: {\n\t\t\t\t\ttooltip: {\n\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\tborderRadius: '16px',\n\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t},\n\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t},\n\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\n\t\tsetMajorJoyrideSteps(majorSteps);\n\t\tsetRunMajorJoyride(true);\n\n\t\t// Fire announcement shown callback\n\t\tif (onAnnouncementShown && storeId) {\n\t\t\tonAnnouncementShown({\n\t\t\t\tstoreId,\n\t\t\t\tannouncementId: feature.id,\n\t\t\t\tannouncementTitle: feature.title,\n\t\t\t\timageUrl: feature.displayImage || feature.image,\n\t\t\t\tvideoUrl: feature.productVideo,\n\t\t\t});\n\t\t}\n\t};\n\n\tconst handleSkipMajorUpdate = useCallback(\n\t\tasync (feature) => {\n\t\t\tconst targetFeature = feature || currentMajorFeature;\n\n\t\t\tif (targetFeature) {\n\t\t\t\tsetIsProcessingMajorUpdate(true);\n\n\t\t\t\tawait Promise.all(\n\t\t\t\t\tmajorUpdateFeatures.map((majorFeature) =>\n\t\t\t\t\t\tmarkFeatureAsViewed(majorFeature.id),\n\t\t\t\t\t),\n\t\t\t\t);\n\n\t\t\t\tsetRunMajorJoyride(false);\n\t\t\t\tsetCurrentMajorFeature(null);\n\t\t\t\tsetMajorJoyrideSteps([]);\n\n\t\t\t\tsetShowMinorUpdates(true);\n\n\t\t\t\t// Fire announcement interacted callback for Skip\n\t\t\t\tif (onAnnouncementInteracted && storeId) {\n\t\t\t\t\tonAnnouncementInteracted({\n\t\t\t\t\t\tstoreId,\n\t\t\t\t\t\tannouncementId: targetFeature.id,\n\t\t\t\t\t\tannouncementTitle: targetFeature.title,\n\t\t\t\t\t\timageUrl: targetFeature.displayImage || targetFeature.image,\n\t\t\t\t\t\tvideoUrl: targetFeature.productVideo,\n\t\t\t\t\t\tbuttonClicked: 'Skip',\n\t\t\t\t\t\tbuttonName: 'Skip',\n\t\t\t\t\t\tbuttonUrl: undefined,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsetIsProcessingMajorUpdate(false);\n\t\t\t\t}, 500);\n\t\t\t} else {\n\t\t\t}\n\t\t},\n\t\t[currentMajorFeature, majorUpdateFeatures, markFeatureAsViewed],\n\t);\n\n\tconst handleExploreFeature = useCallback(\n\t\tasync (feature, triggeredAction?: string) => {\n\t\t\tsetIsProcessingMajorUpdate(true);\n\t\t\t// Await so the feature is marked before any page navigation\n\t\t\tawait markFeatureAsViewed(feature.id);\n\t\t\tconst action = triggeredAction ?? feature.primaryButton?.action;\n\t\t\tif (action === 'Play Video' && feature.productVideo) {\n\t\t\t\tsetVideoUrl(feature.productVideo);\n\t\t\t\tsetIsVideoModalOpen(true);\n\t\t\t\tsetBlockPopups(true);\n\t\t\t}\n\n\t\t\tif (action === 'Open link') {\n\t\t\t\tconst url = feature.primaryButton?.redirectionUrl || feature.redirectUrl;\n\t\t\t\tif (url && !url.startsWith('http')) {\n\t\t\t\t\twindow.location.href = url;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsetRunMajorJoyride(false);\n\t\t\tsetCurrentMajorFeature(null);\n\t\t\tsetMajorJoyrideSteps([]);\n\t\t\tconst currentIndex = majorUpdateFeatures.findIndex(\n\t\t\t\t(f) => f.id === feature.id,\n\t\t\t);\n\t\t\tconst isLastMajorUpdate = currentIndex === majorUpdateFeatures.length - 1;\n\t\t\tif (isLastMajorUpdate) {\n\t\t\t\tsetShowMinorUpdates(true);\n\t\t\t}\n\n\t\t\t// Fire announcement interacted callback for Primary button\n\t\t\tif (onAnnouncementInteracted && storeId) {\n\t\t\t\tonAnnouncementInteracted({\n\t\t\t\t\tstoreId,\n\t\t\t\t\tannouncementId: feature.id,\n\t\t\t\t\tannouncementTitle: feature.title,\n\t\t\t\t\timageUrl: feature.displayImage || feature.image,\n\t\t\t\t\tvideoUrl: feature.productVideo,\n\t\t\t\t\tbuttonClicked: 'Primary',\n\t\t\t\t\tbuttonName: feature.buttonText || 'Explore',\n\t\t\t\t\tbuttonUrl: feature.redirectUrl || feature.productVideo,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tsetIsProcessingMajorUpdate(false);\n\t\t\t}, 500);\n\t\t},\n\t\t[majorUpdateFeatures, markFeatureAsViewed],\n\t);\n\n\tconst handlePreviousMajorUpdate = useCallback(\n\t\t(feature) => {\n\t\t\tconst targetFeature = feature || currentMajorFeature;\n\n\t\t\tif (!targetFeature) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst currentIndex = majorUpdateFeatures.findIndex(\n\t\t\t\t(f) => f.id === targetFeature.id,\n\t\t\t);\n\n\t\t\tif (currentIndex > 0) {\n\t\t\t\tconst prevFeature = majorUpdateFeatures[currentIndex - 1];\n\t\t\t\tsetCurrentMajorFeature(prevFeature);\n\n\t\t\t\tconst prevIndex = currentIndex - 1;\n\t\t\t\tconst totalFeatures = majorUpdateFeatures.length;\n\n\t\t\t\tconst updatedSteps = [\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget: '[data-testid=\"whats-new-button\"]',\n\t\t\t\t\t\tcontent: (\n\t\t\t\t\t\t\t<MajorUpdatePopup\n\t\t\t\t\t\t\t\tfeature={prevFeature}\n\t\t\t\t\t\t\t\tcurrentIndex={prevIndex}\n\t\t\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\t\t\tonSkip={() => handleSkipMajorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tonExplore={(triggeredAction) => handleExploreFeature(prevFeature, triggeredAction)}\n\t\t\t\t\t\t\t\tonPrevious={() => handlePreviousMajorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tonNext={() => handleNextMajorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tsetIsClosing={setIsClosingMajor}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t\tplacement: 'bottom-start',\n\t\t\t\t\t\tplacementBeacon: 'top-end',\n\t\t\t\t\t\tdisableBeacon: true,\n\t\t\t\t\t\thideCloseButton: true,\n\t\t\t\t\t\thideSkipButton: true,\n\t\t\t\t\t\thideFooter: true,\n\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\tdata: { feature: prevFeature, isMajor: true },\n\t\t\t\t\t\tstyles: {\n\t\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\tborderRadius: '16px',\n\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t];\n\n\t\t\t\tsetMajorJoyrideSteps(updatedSteps);\n\t\t\t} else {\n\t\t\t}\n\t\t},\n\t\t[currentMajorFeature, majorUpdateFeatures],\n\t);\n\n\tconst handleNextMajorUpdate = useCallback(\n\t\t(feature) => {\n\t\t\tconst targetFeature = feature || currentMajorFeature;\n\n\t\t\tif (!targetFeature) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst currentIndex = majorUpdateFeatures.findIndex(\n\t\t\t\t(f) => f.id === targetFeature.id,\n\t\t\t);\n\n\t\t\tif (currentIndex < majorUpdateFeatures.length - 1) {\n\t\t\t\tconst nextFeature = majorUpdateFeatures[currentIndex + 1];\n\t\t\t\tsetCurrentMajorFeature(nextFeature);\n\n\t\t\t\tconst nextIndex = currentIndex + 1;\n\t\t\t\tconst totalFeatures = majorUpdateFeatures.length;\n\n\t\t\t\tconst updatedSteps = [\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget: '[data-testid=\"whats-new-button\"]',\n\t\t\t\t\t\tcontent: (\n\t\t\t\t\t\t\t<MajorUpdatePopup\n\t\t\t\t\t\t\t\tfeature={nextFeature}\n\t\t\t\t\t\t\t\tcurrentIndex={nextIndex}\n\t\t\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\t\t\tonSkip={() => handleSkipMajorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tonExplore={(triggeredAction) => handleExploreFeature(nextFeature, triggeredAction)}\n\t\t\t\t\t\t\t\tonPrevious={() => handlePreviousMajorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tonNext={() => handleNextMajorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tsetIsClosing={setIsClosingMajor}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t\tplacement: 'bottom-start',\n\t\t\t\t\t\tplacementBeacon: 'top-end',\n\t\t\t\t\t\tdisableBeacon: true,\n\t\t\t\t\t\thideCloseButton: true,\n\t\t\t\t\t\thideSkipButton: true,\n\t\t\t\t\t\thideFooter: true,\n\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\tdata: { feature: nextFeature, isMajor: true },\n\t\t\t\t\t\tstyles: {\n\t\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\tborderRadius: '16px',\n\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t];\n\n\t\t\t\tsetMajorJoyrideSteps(updatedSteps);\n\t\t\t} else {\n\t\t\t\tsetIsProcessingMajorUpdate(true);\n\n\t\t\t\tmarkFeatureAsViewed(targetFeature.id);\n\t\t\t\tsetRunMajorJoyride(false);\n\t\t\t\tsetCurrentMajorFeature(null);\n\t\t\t\tsetMajorJoyrideSteps([]);\n\n\t\t\t\tsetShowMinorUpdates(true);\n\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsetIsProcessingMajorUpdate(false);\n\t\t\t\t}, 500);\n\t\t\t}\n\t\t},\n\t\t[currentMajorFeature, majorUpdateFeatures, markFeatureAsViewed],\n\t);\n\n\tconst showMajorUpdatePopup = () => {\n\t\tif (majorUpdateFeatures.length > 0 && !currentMajorFeature) {\n\t\t\tconst whatsNewButton = document.querySelector(\n\t\t\t\t'[data-testid=\"whats-new-button\"]',\n\t\t\t);\n\n\t\t\tif (whatsNewButton) {\n\t\t\t\tshowMajorUpdateJoyride(majorUpdateFeatures[0]);\n\t\t\t}\n\t\t}\n\t};\n\n\tuseEffect(() => {\n\t\t(window as any).showMajorUpdatePopup = showMajorUpdatePopup;\n\t\treturn () => {\n\t\t\tdelete (window as any).showMajorUpdatePopup;\n\t\t};\n\t}, [majorUpdateFeatures, currentMajorFeature]);\n\tconst handleMajorJoyrideCallback = useCallback(\n\t\t(data) => {\n\t\t\tconst { action } = data;\n\n\t\t\tif (action === ACTIONS.CLOSE) {\n\t\t\t\tif (currentMajorFeature) {\n\t\t\t\t\tsetIsProcessingMajorUpdate(true);\n\n\t\t\t\t\tmajorUpdateFeatures.forEach((majorFeature) => {\n\t\t\t\t\t\tmarkFeatureAsViewed(majorFeature.id);\n\t\t\t\t\t});\n\n\t\t\t\t\tsetShowMinorUpdates(true);\n\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tsetIsProcessingMajorUpdate(false);\n\t\t\t\t\t}, 500);\n\t\t\t\t}\n\n\t\t\t\tsetRunMajorJoyride(false);\n\t\t\t\tsetCurrentMajorFeature(null);\n\t\t\t\tsetMajorJoyrideSteps([]);\n\t\t\t}\n\t\t},\n\t\t[currentMajorFeature, majorUpdateFeatures, markFeatureAsViewed],\n\t);\n\n\tconst handleMinorJoyrideCallback = useCallback(\n\t\t(data) => {\n\t\t\tconst { action } = data;\n\n\t\t\tif (action === ACTIONS.CLOSE) {\n\t\t\t\tif (currentMinorFeature) {\n\t\t\t\t\tsetIsProcessingMinorUpdate(true);\n\n\t\t\t\t\t// Only mark the current feature as viewed, not all features\n\t\t\t\t\tmarkFeatureAsViewed(currentMinorFeature.id);\n\n\t\t\t\t\t// Check if there are more features to show\n\t\t\t\t\tconst currentIndex = availableMinorFeatures.findIndex(\n\t\t\t\t\t\t(f) => f.id === currentMinorFeature.id,\n\t\t\t\t\t);\n\t\t\t\t\tconst isLastFeature =\n\t\t\t\t\t\tcurrentIndex === availableMinorFeatures.length - 1;\n\n\t\t\t\t\tif (isLastFeature) {\n\t\t\t\t\t\t// Only skip remaining features if this was the last one\n\t\t\t\t\t\tsetMinorFeaturesSkipped(true);\n\t\t\t\t\t}\n\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tsetIsProcessingMinorUpdate(false);\n\t\t\t\t\t}, 500);\n\t\t\t\t}\n\n\t\t\t\tsetRunJoyride(false);\n\t\t\t\tsetCurrentMinorFeature(null);\n\t\t\t\tsetJoyrideSteps([]);\n\t\t\t}\n\t\t},\n\t\t[currentMinorFeature, availableMinorFeatures, markFeatureAsViewed],\n\t);\n\tconst showMinorUpdateJoyride = async (feature, featuresToUse?) => {\n\t\tsetCurrentMinorFeature(feature);\n\n\t\t// Use provided features array or fall back to state (for test mode)\n\t\tconst features = featuresToUse || availableMinorFeatures;\n\t\tconst currentIndex = features.findIndex((f) => f.id === feature.id);\n\t\tconst totalFeatures = features.length;\n\n\t\tconst targetSelector =\n\t\t\tfeature.featureTag.startsWith('#') ||\n\t\t\tfeature.featureTag.startsWith('.') ||\n\t\t\tfeature.featureTag.startsWith('[')\n\t\t\t\t? feature.featureTag\n\t\t\t\t: `#${feature.featureTag}`;\n\n\t\t// Scroll to target element smoothly before showing popup\n\t\tconst targetElement = document.querySelector(targetSelector);\n\t\tif (targetElement) {\n\t\t\ttry {\n\t\t\t\t// Dynamically import to avoid circular dependencies\n\t\t\t\tconst { scrollToElementSmooth } = await import(\n\t\t\t\t\t'./utils/elementHelpers'\n\t\t\t\t);\n\t\t\t\tawait scrollToElementSmooth(targetElement, 120);\n\t\t\t} catch (error) {\n\t\t\t\t// Scroll failed silently\n\t\t\t}\n\t\t}\n\n\t\tconst minorSteps = [\n\t\t\t{\n\t\t\t\ttarget: targetSelector,\n\t\t\t\tcontent: (\n\t\t\t\t\t<MinorUpdatePopup\n\t\t\t\t\t\tfeature={feature}\n\t\t\t\t\t\tcurrentIndex={currentIndex}\n\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\tonSkip={() => handleSkipMinorUpdate(feature)}\n\t\t\t\t\t\tonExplore={(triggeredAction) => handleExploreMinorFeature(feature, triggeredAction)}\n\t\t\t\t\t\tonPrevious={() => handlePreviousMinorUpdate(feature)}\n\t\t\t\t\t\tonNext={() => handleNextMinorUpdate(feature)}\n\t\t\t\t\t\tsetIsClosing={setIsClosingMinor}\n\t\t\t\t\t/>\n\t\t\t\t),\n\t\t\t\tplacement: 'bottom',\n\t\t\t\tplacementBeacon: 'bottom-end',\n\t\t\t\tdisableBeacon: true,\n\t\t\t\thideCloseButton: true,\n\t\t\t\thideSkipButton: true,\n\t\t\t\thideFooter: true,\n\t\t\t\toffset: 0,\n\t\t\t\tdata: { feature, isMinor: true },\n\t\t\t\tstyles: {\n\t\t\t\t\ttooltip: {\n\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t},\n\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t},\n\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\t\tsetJoyrideSteps(minorSteps);\n\t\tsetRunJoyride(true);\n\t};\n\n\tconst handleSkipMinorUpdate = useCallback(\n\t\tasync (feature) => {\n\t\t\tconst targetFeature = feature || currentMinorFeature;\n\n\t\t\tif (targetFeature) {\n\t\t\t\tsetIsProcessingMinorUpdate(true);\n\n\t\t\t\t// Only mark the current feature as viewed, not all features\n\t\t\t\tawait markFeatureAsViewed(targetFeature.id);\n\n\t\t\t\t// Add to session tracker to prevent re-showing\n\t\t\t\tsetShownMinorFeatureIds((prev) => new Set(prev).add(targetFeature.id));\n\n\t\t\t\tsetRunJoyride(false);\n\t\t\t\tsetCurrentMinorFeature(null);\n\t\t\t\tsetJoyrideSteps([]);\n\n\t\t\t\t// Find next unshown feature\n\t\t\t\tconst nextFeature = availableMinorFeatures.find(\n\t\t\t\t\t(f) => f.id !== targetFeature.id && !shownMinorFeatureIds.has(f.id),\n\t\t\t\t);\n\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsetIsProcessingMinorUpdate(false);\n\n\t\t\t\t\tif (nextFeature) {\n\t\t\t\t\t\t// Auto-advance to next feature\n\t\t\t\t\t\tshowMinorUpdateJoyride(nextFeature, availableMinorFeatures);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// No more features to show\n\t\t\t\t\t\tsetMinorFeaturesSkipped(true);\n\t\t\t\t\t}\n\t\t\t\t}, 500);\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\tcurrentMinorFeature,\n\t\t\tavailableMinorFeatures,\n\t\t\tmarkFeatureAsViewed,\n\t\t\tshownMinorFeatureIds,\n\t\t],\n\t);\n\n\tconst handleExploreMinorFeature = useCallback(\n\t\tasync (feature, triggeredAction?: string) => {\n\t\t\tsetIsProcessingMinorUpdate(true);\n\n\t\t\t// Only mark the current feature as viewed\n\t\t\t// Await so the feature is marked before any page navigation\n\t\t\tawait markFeatureAsViewed(feature.id);\n\n\t\t\t// Add to session tracker to prevent re-showing\n\t\t\tsetShownMinorFeatureIds((prev) => new Set(prev).add(feature.id));\n\n\t\t\tconst action = triggeredAction ?? feature.primaryButton?.action;\n\n\t\t\tif (action === 'Play Video' && feature.productVideo) {\n\t\t\t\tsetVideoUrl(feature.productVideo);\n\t\t\t\tsetIsVideoModalOpen(true);\n\t\t\t\tsetBlockPopups(true);\n\t\t\t}\n\n\t\t\tif (action === 'Open link') {\n\t\t\t\tconst url = feature.primaryButton?.redirectionUrl || feature.redirectUrl;\n\t\t\t\tif (url && !url.startsWith('http')) {\n\t\t\t\t\twindow.location.href = url;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsetRunJoyride(false);\n\t\t\tsetCurrentMinorFeature(null);\n\t\t\tsetJoyrideSteps([]);\n\n\t\t\t// Find next unshown feature (only auto-advance if no video modal)\n\t\t\tconst nextFeature = availableMinorFeatures.find(\n\t\t\t\t(f) => f.id !== feature.id && !shownMinorFeatureIds.has(f.id),\n\t\t\t);\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tsetIsProcessingMinorUpdate(false);\n\n\t\t\t\t// Only auto-advance if no video modal is opened\n\t\t\t\tif (nextFeature && action !== 'Play Video') {\n\t\t\t\t\t// Auto-advance to next feature\n\t\t\t\t\tshowMinorUpdateJoyride(nextFeature, availableMinorFeatures);\n\t\t\t\t} else if (!nextFeature) {\n\t\t\t\t\t// No more features to show\n\t\t\t\t\tsetMinorFeaturesSkipped(true);\n\t\t\t\t}\n\t\t\t\t// If video modal opened, wait for user to close it before advancing\n\t\t\t}, 500);\n\t\t},\n\t\t[availableMinorFeatures, markFeatureAsViewed, shownMinorFeatureIds],\n\t);\n\n\tconst handlePreviousMinorUpdate = useCallback(\n\t\tasync (feature) => {\n\t\t\tconst targetFeature = feature || currentMinorFeature;\n\n\t\t\tif (!targetFeature) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst currentIndex = availableMinorFeatures.findIndex(\n\t\t\t\t(f) => f.id === targetFeature.id,\n\t\t\t);\n\n\t\t\tif (currentIndex > 0) {\n\t\t\t\tconst prevFeature = availableMinorFeatures[currentIndex - 1];\n\t\t\t\tsetCurrentMinorFeature(prevFeature);\n\n\t\t\t\tconst targetSelector =\n\t\t\t\t\tprevFeature.featureTag.startsWith('#') ||\n\t\t\t\t\tprevFeature.featureTag.startsWith('.') ||\n\t\t\t\t\tprevFeature.featureTag.startsWith('[')\n\t\t\t\t\t\t? prevFeature.featureTag\n\t\t\t\t\t\t: `#${prevFeature.featureTag}`;\n\n\t\t\t\t// Scroll to the previous feature element\n\t\t\t\tconst targetElement = document.querySelector(targetSelector);\n\t\t\t\tif (targetElement) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst { scrollToElementSmooth } = await import(\n\t\t\t\t\t\t\t'./utils/elementHelpers'\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait scrollToElementSmooth(targetElement, 120);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t// Scroll failed silently\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst prevIndex = currentIndex - 1;\n\t\t\t\tconst totalFeatures = availableMinorFeatures.length;\n\n\t\t\t\tconst updatedSteps = [\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget: targetSelector,\n\t\t\t\t\t\tcontent: (\n\t\t\t\t\t\t\t<MinorUpdatePopup\n\t\t\t\t\t\t\t\tfeature={prevFeature}\n\t\t\t\t\t\t\t\tcurrentIndex={prevIndex}\n\t\t\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\t\t\tonSkip={() => handleSkipMinorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tonExplore={(triggeredAction) => handleExploreMinorFeature(prevFeature, triggeredAction)}\n\t\t\t\t\t\t\t\tonPrevious={() => handlePreviousMinorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tonNext={() => handleNextMinorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tsetIsClosing={setIsClosingMinor}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t\tplacement: 'bottom',\n\t\t\t\t\t\tplacementBeacon: 'bottom-end',\n\t\t\t\t\t\tdisableBeacon: true,\n\t\t\t\t\t\thideCloseButton: true,\n\t\t\t\t\t\thideSkipButton: true,\n\t\t\t\t\t\thideFooter: true,\n\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\tdata: { feature: prevFeature, isMinor: true },\n\t\t\t\t\t\tstyles: {\n\t\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t];\n\n\t\t\t\tsetJoyrideSteps(updatedSteps);\n\t\t\t}\n\t\t},\n\t\t[currentMinorFeature, availableMinorFeatures],\n\t);\n\n\tconst handleNextMinorUpdate = useCallback(\n\t\tasync (feature) => {\n\t\t\tconst targetFeature = feature || currentMinorFeature;\n\n\t\t\tif (!targetFeature) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst currentIndex = availableMinorFeatures.findIndex(\n\t\t\t\t(f) => f.id === targetFeature.id,\n\t\t\t);\n\n\t\t\tif (currentIndex < availableMinorFeatures.length - 1) {\n\t\t\t\tconst nextFeature = availableMinorFeatures[currentIndex + 1];\n\t\t\t\tsetCurrentMinorFeature(nextFeature);\n\n\t\t\t\tconst targetSelector =\n\t\t\t\t\tnextFeature.featureTag.startsWith('#') ||\n\t\t\t\t\tnextFeature.featureTag.startsWith('.') ||\n\t\t\t\t\tnextFeature.featureTag.startsWith('[')\n\t\t\t\t\t\t? nextFeature.featureTag\n\t\t\t\t\t\t: `#${nextFeature.featureTag}`;\n\n\t\t\t\t// Scroll to the next feature element\n\t\t\t\tconst targetElement = document.querySelector(targetSelector);\n\t\t\t\tif (targetElement) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst { scrollToElementSmooth } = await import(\n\t\t\t\t\t\t\t'./utils/elementHelpers'\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait scrollToElementSmooth(targetElement, 120);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t// Scroll failed silently\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst nextIndex = currentIndex + 1;\n\t\t\t\tconst totalFeatures = availableMinorFeatures.length;\n\n\t\t\t\tconst updatedSteps = [\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget: targetSelector,\n\t\t\t\t\t\tcontent: (\n\t\t\t\t\t\t\t<MinorUpdatePopup\n\t\t\t\t\t\t\t\tfeature={nextFeature}\n\t\t\t\t\t\t\t\tcurrentIndex={nextIndex}\n\t\t\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\t\t\tonSkip={() => handleSkipMinorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tonExplore={(triggeredAction) => handleExploreMinorFeature(nextFeature, triggeredAction)}\n\t\t\t\t\t\t\t\tonPrevious={() => handlePreviousMinorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tonNext={() => handleNextMinorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tsetIsClosing={setIsClosingMinor}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t\tplacement: 'bottom',\n\t\t\t\t\t\tplacementBeacon: 'bottom-end',\n\t\t\t\t\t\tdisableBeacon: true,\n\t\t\t\t\t\thideCloseButton: true,\n\t\t\t\t\t\thideSkipButton: true,\n\t\t\t\t\t\thideFooter: true,\n\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\tdata: { feature: nextFeature, isMinor: true },\n\t\t\t\t\t\tstyles: {\n\t\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t];\n\n\t\t\t\tsetJoyrideSteps(updatedSteps);\n\t\t\t} else {\n\t\t\t\tsetIsProcessingMinorUpdate(true);\n\t\t\t\tsetMinorFeaturesSkipped(true);\n\n\t\t\t\tmarkFeatureAsViewed(targetFeature.id);\n\t\t\t\tsetRunJoyride(false);\n\t\t\t\tsetCurrentMinorFeature(null);\n\t\t\t\tsetJoyrideSteps([]);\n\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsetIsProcessingMinorUpdate(false);\n\t\t\t\t}, 500);\n\t\t\t}\n\t\t},\n\t\t[currentMinorFeature, availableMinorFeatures, markFeatureAsViewed],\n\t);\n\n\treturn (\n\t\t<>\n\t\t\t{children}\n\n\t\t\t{majorJoyrideSteps.length > 0 && (\n\t\t\t\t<Joyride\n\t\t\t\t\tkey={`major-joyride-${majorJoyrideKey}`}\n\t\t\t\t\tsteps={majorJoyrideSteps}\n\t\t\t\t\trun={runMajorJoyride}\n\t\t\t\t\tcontinuous={false}\n\t\t\t\t\tshowProgress={false}\n\t\t\t\t\tshowSkipButton={false}\n\t\t\t\t\tcallback={handleMajorJoyrideCallback}\n\t\t\t\t\tdisableOverlayClose={false}\n\t\t\t\t\tdisableCloseOnEsc={false}\n\t\t\t\t\tdisableOverlay={false}\n\t\t\t\t\tspotlightClicks={false}\n\t\t\t\t\tstyles={{\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tprimaryColor: '#007bff',\n\t\t\t\t\t\t\tzIndex: 10000,\n\t\t\t\t\t\t\twidth: 'auto',\n\t\t\t\t\t\t\tarrowColor: isClosingMajor ? 'transparent' : '#212121',\n\t\t\t\t\t\t},\n\t\t\t\t\t\toverlay: {\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tspotlight: {\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\tborderRadius: '16px',\n\t\t\t\t\t\t\tfontSize: '14px',\n\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t}}\n\t\t\t\t\tlocale={{\n\t\t\t\t\t\tback: 'Back',\n\t\t\t\t\t\tclose: 'Close',\n\t\t\t\t\t\tlast: 'Close',\n\t\t\t\t\t\tnext: 'Next',\n\t\t\t\t\t\tskip: 'Skip',\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{joyrideSteps.length > 0 && (\n\t\t\t\t<Joyride\n\t\t\t\t\tkey={`minor-joyride-${minorJoyrideKey}`}\n\t\t\t\t\tsteps={joyrideSteps}\n\t\t\t\t\trun={runJoyride}\n\t\t\t\t\tcontinuous={false}\n\t\t\t\t\tshowProgress={false}\n\t\t\t\t\tshowSkipButton={false}\n\t\t\t\t\tcallback={handleMinorJoyrideCallback}\n\t\t\t\t\tdisableOverlayClose={false}\n\t\t\t\t\tdisableCloseOnEsc={false}\n\t\t\t\t\tdisableOverlay={false}\n\t\t\t\t\tscrollToFirstStep={true}\n\t\t\t\t\tscrollOffset={120}\n\t\t\t\t\tdisableScrolling={false}\n\t\t\t\t\tstyles={{\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tprimaryColor: '#007bff',\n\t\t\t\t\t\t\tzIndex: 10000,\n\t\t\t\t\t\t\twidth: 'auto',\n\t\t\t\t\t\t\tarrowColor: isClosingMinor ? 'transparent' : '#ffffff',\n\t\t\t\t\t\t},\n\t\t\t\t\t\toverlay: {\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tspotlight: {\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\tborderRadius: '8px',\n\t\t\t\t\t\t\tboxShadow: isClosingMinor\n\t\t\t\t\t\t\t\t? 'none'\n\t\t\t\t\t\t\t\t: '0 0 0 9999px rgba(0, 0, 0, 0.4), 0 0 0 3px rgba(255, 255, 255, 0.8), 0 0 20px 8px rgba(255, 255, 255, 0.4)',\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\tfontSize: '14px',\n\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t}}\n\t\t\t\t\tlocale={{\n\t\t\t\t\t\tback: 'Back',\n\t\t\t\t\t\tclose: 'Close',\n\t\t\t\t\t\tlast: 'Close',\n\t\t\t\t\t\tnext: 'Next',\n\t\t\t\t\t\tskip: 'Skip',\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t<VideoModal\n\t\t\t\tisOpen={isVideoModalOpen}\n\t\t\t\tvideoUrl={videoUrl}\n\t\t\t\tonClose={() => {\n\t\t\t\t\tsetIsVideoModalOpen(false);\n\t\t\t\t\tsetVideoUrl('');\n\t\t\t\t\tsetBlockPopups(false);\n\n\t\t\t\t\t// After video modal closes, check if there are more features to show\n\t\t\t\t\tconst nextFeature = availableMinorFeatures.find(\n\t\t\t\t\t\t(f) => !shownMinorFeatureIds.has(f.id),\n\t\t\t\t\t);\n\n\t\t\t\t\tif (nextFeature) {\n\t\t\t\t\t\t// Auto-advance to next feature after video\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\tshowMinorUpdateJoyride(nextFeature, availableMinorFeatures);\n\t\t\t\t\t\t}, 300);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// No more features to show\n\t\t\t\t\t\tsetMinorFeaturesSkipped(true);\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t/>\n\t\t</>\n\t);\n\n};\n\nexport default FeatureAnnouncementProvider;\n"],"names":["FeatureAnnouncementProvider","_ref","children","fetchVisibleFeatures","getStoreFeatureProgress","fetchFeatureById","markFeatureAsViewedForStore","isFeatureApplicableToCurrentPage","module","router","storeId","onAnnouncementShown","onAnnouncementInteracted","majorUpdateFeatures","minorUpdateFeatures","isLoading","markFeatureAsViewed","useFeatureAnnouncements","currentMajorFeature","setCurrentMajorFeature","useState","currentMinorFeature","setCurrentMinorFeature","runJoyride","setRunJoyride","joyrideSteps","setJoyrideSteps","runMajorJoyride","setRunMajorJoyride","majorJoyrideSteps","setMajorJoyrideSteps","isProcessingMajorUpdate","setIsProcessingMajorUpdate","isProcessingMinorUpdate","setIsProcessingMinorUpdate","availableMinorFeatures","setAvailableMinorFeatures","minorFeaturesSkipped","setMinorFeaturesSkipped","showMinorUpdates","setShowMinorUpdates","isVideoModalOpen","setIsVideoModalOpen","videoUrl","setVideoUrl","blockPopups","setBlockPopups","isClosingMajor","setIsClosingMajor","isClosingMinor","setIsClosingMinor","majorJoyrideKey","setMajorJoyrideKey","minorJoyrideKey","setMinorJoyrideKey","shownMinorFeatureIds","setShownMinorFeatureIds","Set","useEffect","styleId","styleElement","document","getElementById","createElement","id","head","appendChild","textContent","el","remove","prev","pathname","length","attempts","MAX_ATTEMPTS","checkWhatsNewButton","querySelector","showMajorUpdateJoyride","setTimeout","featureIdFromQuery","_a","query","forcedFeature","find","f","featureTag","interval","setInterval","targetSelector","startsWith","testModeFeatures","showMinorUpdateJoyride","clearInterval","observer","scrollListener","checkTimeout","isCleanedUp","checkElementsAndStartTour","availableFeatures","filter","feature","trim","has","disconnect","window","removeEventListener","clearTimeout","MutationObserver","mutations","shouldCheck","mutation","type","addedNodes","i","node","nodeType","Node","ELEMENT_NODE","element","requestAnimationFrame","observe","body","childList","subtree","addEventListener","passive","currentIndex","findIndex","totalFeatures","majorSteps","target","SELECTORS","WHATS_NEW_BUTTON","content","_jsx","MajorUpdatePopup","onSkip","handleSkipMajorUpdate","onExplore","triggeredAction","handleExploreFeature","onPrevious","handlePreviousMajorUpdate","onNext","handleNextMajorUpdate","setIsClosing","placement","placementBeacon","disableBeacon","hideCloseButton","hideSkipButton","hideFooter","offset","data","isMajor","styles","tooltip","padding","backgroundColor","borderRadius","border","boxShadow","tooltipContent","buttonNext","display","buttonBack","buttonClose","buttonSkip","announcementId","announcementTitle","title","imageUrl","displayImage","image","productVideo","useCallback","__awaiter","targetFeature","Promise","all","map","majorFeature","buttonClicked","buttonName","buttonUrl","undefined","action","_b","primaryButton","url","_c","redirectionUrl","redirectUrl","location","href","buttonText","prevFeature","prevIndex","updatedSteps","nextFeature","nextIndex","showMajorUpdatePopup","handleMajorJoyrideCallback","ACTIONS","CLOSE","forEach","handleMinorJoyrideCallback","featuresToUse","features","targetElement","scrollToElementSmooth","import","error","minorSteps","MinorUpdatePopup","handleSkipMinorUpdate","handleExploreMinorFeature","handlePreviousMinorUpdate","handleNextMinorUpdate","isMinor","add","_d","_e","_jsxs","_Fragment","Joyride","steps","run","continuous","showProgress","showSkipButton","callback","disableOverlayClose","disableCloseOnEsc","disableOverlay","spotlightClicks","options","primaryColor","zIndex","width","arrowColor","overlay","spotlight","fontSize","locale","back","close","last","next","skip","scrollToFirstStep","scrollOffset","disableScrolling","VideoModal","isOpen","onClose"],"mappings":"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"}
1
+ {"version":3,"file":"FeatureAnnouncementProvider.js","sources":["../../../../src/components/feature-announcements/FeatureAnnouncementProvider.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useState } from 'react';\nimport Joyride, { ACTIONS } from 'react-joyride';\nimport { SELECTORS } from './constants';\nimport { useFeatureAnnouncements } from './hooks';\nimport MajorUpdatePopup from './MajorUpdatePopup';\nimport MinorUpdatePopup from './MinorUpdatePopup';\nimport { FeatureAnnouncement, FeatureAnnouncementProviderProps } from './types';\nimport { VideoModal } from './VideoModal';\n\nconst FeatureAnnouncementProvider: React.FC<\n\tFeatureAnnouncementProviderProps\n> = ({\n\tchildren,\n\tfetchVisibleFeatures,\n\tgetStoreFeatureProgress,\n\tfetchFeatureById,\n\tmarkFeatureAsViewedForStore,\n\tisFeatureApplicableToCurrentPage,\n\tmodule,\n\trouter,\n\tstoreId,\n\tonAnnouncementShown,\n\tonAnnouncementInteracted,\n}) => {\n\tconst {\n\t\tmajorUpdateFeatures,\n\t\tminorUpdateFeatures,\n\t\tisLoading,\n\t\tmarkFeatureAsViewed,\n\t} = useFeatureAnnouncements({\n\t\tfetchVisibleFeatures,\n\t\tgetStoreFeatureProgress,\n\t\tfetchFeatureById,\n\t\tmarkFeatureAsViewedForStore,\n\t\tisFeatureApplicableToCurrentPage,\n\t\tmodule,\n\t\trouter,\n\t});\n\n\tconst [currentMajorFeature, setCurrentMajorFeature] =\n\t\tuseState<FeatureAnnouncement | null>(null);\n\tconst [currentMinorFeature, setCurrentMinorFeature] =\n\t\tuseState<FeatureAnnouncement | null>(null);\n\tconst [runJoyride, setRunJoyride] = useState(false);\n\tconst [joyrideSteps, setJoyrideSteps] = useState<any[]>([]);\n\tconst [runMajorJoyride, setRunMajorJoyride] = useState(false);\n\tconst [majorJoyrideSteps, setMajorJoyrideSteps] = useState<any[]>([]);\n\tconst [isProcessingMajorUpdate, setIsProcessingMajorUpdate] = useState(false);\n\tconst [isProcessingMinorUpdate, setIsProcessingMinorUpdate] = useState(false);\n\tconst [availableMinorFeatures, setAvailableMinorFeatures] = useState<\n\t\tFeatureAnnouncement[]\n\t>([]);\n\tconst [minorFeaturesSkipped, setMinorFeaturesSkipped] = useState(false);\n\tconst [showMinorUpdates, setShowMinorUpdates] = useState(false);\n\tconst [isVideoModalOpen, setIsVideoModalOpen] = useState(false);\n\tconst [videoUrl, setVideoUrl] = useState('');\n\tconst [blockPopups, setBlockPopups] = useState(false);\n\tconst [isClosingMajor, setIsClosingMajor] = useState(false);\n\tconst [isClosingMinor, setIsClosingMinor] = useState(false);\n\tconst [majorJoyrideKey, setMajorJoyrideKey] = useState(0);\n\tconst [minorJoyrideKey, setMinorJoyrideKey] = useState(0);\n\tconst [shownMinorFeatureIds, setShownMinorFeatureIds] = useState<Set<string>>(\n\t\tnew Set(),\n\t);\n\n\t// Add custom style for spotlight cutout effect\n\tuseEffect(() => {\n\t\tconst styleId = 'minor-spotlight-cutout-style';\n\t\tlet styleElement = document.getElementById(styleId) as HTMLStyleElement;\n\n\t\tif (!styleElement) {\n\t\t\tstyleElement = document.createElement('style');\n\t\t\tstyleElement.id = styleId;\n\t\t\tdocument.head.appendChild(styleElement);\n\t\t}\n\n\t\tstyleElement.textContent = `\n\t\t\t.react-joyride__spotlight {\n\t\t\t\ttransition: box-shadow 0.3s ease-in-out !important;\n\t\t\t\twill-change: box-shadow, transform;\n\t\t\t\ttransform: translateZ(0);\n\t\t\t}\n\t\t\t.react-joyride__tooltip {\n\t\t\t\twill-change: transform, opacity;\n\t\t\t\ttransform: translateZ(0);\n\t\t\t}\n\t\t\t.react-joyride__floater {\n\t\t\t\tright: 12px !important;\n\t\t\t\tleft: auto !important;\n\t\t\t}\n\t\t`;\n\n\t\treturn () => {\n\t\t\tconst el = document.getElementById(styleId);\n\t\t\tif (el) {\n\t\t\t\tel.remove();\n\t\t\t}\n\t\t};\n\t}, []);\n\n\t// Force Joyride remount on navigation to prevent stale state\n\tuseEffect(() => {\n\t\tsetMajorJoyrideKey((prev) => prev + 1);\n\t\tsetMinorJoyrideKey((prev) => prev + 1);\n\t\tsetIsClosingMajor(false);\n\t\tsetIsClosingMinor(false);\n\t\t// Reset session tracking on navigation to allow features to show on new pages\n\t\tsetShownMinorFeatureIds(new Set());\n\t}, [router?.pathname]);\n\n\tuseEffect(() => {\n\t\tif (\n\t\t\tmajorUpdateFeatures.length > 0 &&\n\t\t\t!currentMajorFeature &&\n\t\t\t!isLoading &&\n\t\t\t!isProcessingMajorUpdate &&\n\t\t\t!blockPopups\n\t\t) {\n\t\t\tsetShowMinorUpdates(false);\n\t\t\tsetMinorFeaturesSkipped(false);\n\t\t\tsetRunJoyride(false);\n\t\t\tsetJoyrideSteps([]);\n\t\t\tsetCurrentMinorFeature(null);\n\t\t\tsetAvailableMinorFeatures([]);\n\n\t\t\tlet attempts = 0;\n\t\t\tconst MAX_ATTEMPTS = 10;\n\n\t\t\tconst checkWhatsNewButton = () => {\n\t\t\t\tattempts++;\n\t\t\t\tconst whatsNewButton = document.querySelector(\n\t\t\t\t\t'[data-testid=\"whats-new-button\"]',\n\t\t\t\t);\n\n\t\t\t\tif (whatsNewButton) {\n\t\t\t\t\tshowMajorUpdateJoyride(majorUpdateFeatures[0]);\n\t\t\t\t} else if (attempts < MAX_ATTEMPTS) {\n\t\t\t\t\tsetTimeout(checkWhatsNewButton, 1000);\n\t\t\t\t} else {\n\t\t\t\t\tsetShowMinorUpdates(true);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tcheckWhatsNewButton();\n\t\t} else if (majorUpdateFeatures.length === 0 && !isLoading) {\n\t\t\tsetShowMinorUpdates(true);\n\t\t}\n\t}, [\n\t\tmajorUpdateFeatures,\n\t\tcurrentMajorFeature,\n\t\tisLoading,\n\t\tisProcessingMajorUpdate,\n\t\tblockPopups,\n\t]);\n\n\tuseEffect(() => {\n\t\t// Only run this special logic if a feature is being forced via URL\n\t\tconst featureIdFromQuery = router?.query?.['featureId'] as string;\n\n\t\tif (!featureIdFromQuery || isLoading || minorUpdateFeatures.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst forcedFeature = minorUpdateFeatures.find(\n\t\t\t(f) => f.id === featureIdFromQuery,\n\t\t);\n\n\t\tif (!forcedFeature || !forcedFeature.featureTag) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Prevent the standard flow from interfering\n\t\tsetMinorFeaturesSkipped(true);\n\t\t// Mark that we're processing to prevent other effects from interfering\n\t\tsetIsProcessingMinorUpdate(true);\n\n\t\tlet attempts = 0;\n\t\tconst maxAttempts = 25; // 5 seconds\n\t\tconst interval = setInterval(() => {\n\t\t\tattempts++;\n\t\t\tconst targetSelector =\n\t\t\t\tforcedFeature.featureTag.startsWith('#') ||\n\t\t\t\tforcedFeature.featureTag.startsWith('.') ||\n\t\t\t\tforcedFeature.featureTag.startsWith('[')\n\t\t\t\t\t? forcedFeature.featureTag\n\t\t\t\t\t: `#${forcedFeature.featureTag}`;\n\n\t\t\tconst element = document.querySelector(targetSelector);\n\n\t\t\tif (element) {\n\t\t\t\t// In test mode, pass the feature array directly to avoid async state issues\n\t\t\t\tconst testModeFeatures = [forcedFeature];\n\t\t\t\tsetAvailableMinorFeatures(testModeFeatures);\n\t\t\t\tshowMinorUpdateJoyride(forcedFeature, testModeFeatures);\n\t\t\t\t// Don't reset processing flag here - let user interaction handle it\n\t\t\t\t// This prevents auto-closing when multiple popups exist or when scrolling\n\t\t\t\tclearInterval(interval);\n\t\t\t} else if (attempts >= maxAttempts) {\n\t\t\t\t// Fallback for safety, though user expects it to be there.\n\t\t\t\t// We could log an error here.\n\t\t\t\t// Only reset on timeout (element not found)\n\t\t\t\tsetIsProcessingMinorUpdate(false);\n\t\t\t\tclearInterval(interval);\n\t\t\t}\n\t\t}, 200);\n\n\t\treturn () => {\n\t\t\tclearInterval(interval);\n\t\t\t// Don't reset processing flag on cleanup - it causes premature popup closure\n\t\t\t// The flag will be managed by user interactions (skip/explore handlers)\n\t\t};\n\t}, [minorUpdateFeatures, router?.query?.['featureId'], isLoading]);\n\n\tuseEffect(() => {\n\t\tif (\n\t\t\tminorUpdateFeatures.length > 0 &&\n\t\t\t!isLoading &&\n\t\t\t!runJoyride &&\n\t\t\t!isProcessingMinorUpdate &&\n\t\t\t!currentMinorFeature &&\n\t\t\t!minorFeaturesSkipped &&\n\t\t\tshowMinorUpdates &&\n\t\t\t!blockPopups\n\t\t) {\n\t\t\tlet observer: MutationObserver | null = null;\n\t\t\tlet scrollListener: (() => void) | null = null;\n\t\t\tlet checkTimeout: ReturnType<typeof setTimeout> | null = null;\n\t\t\tlet isCleanedUp = false;\n\n\t\t\tconst checkElementsAndStartTour = () => {\n\t\t\t\tif (\n\t\t\t\t\tisCleanedUp ||\n\t\t\t\t\tisProcessingMinorUpdate ||\n\t\t\t\t\tcurrentMinorFeature ||\n\t\t\t\t\tminorFeaturesSkipped ||\n\t\t\t\t\t!showMinorUpdates\n\t\t\t\t)\n\t\t\t\t\treturn;\n\n\t\t\t\tconst availableFeatures = minorUpdateFeatures.filter((feature) => {\n\t\t\t\t\tif (!feature.featureTag || feature.featureTag.trim() === '') {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Skip features already shown in this session\n\t\t\t\t\tif (shownMinorFeatureIds.has(feature.id)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst targetSelector =\n\t\t\t\t\t\tfeature.featureTag.startsWith('#') ||\n\t\t\t\t\t\tfeature.featureTag.startsWith('.') ||\n\t\t\t\t\t\tfeature.featureTag.startsWith('[')\n\t\t\t\t\t\t\t? feature.featureTag\n\t\t\t\t\t\t\t: `#${feature.featureTag}`;\n\n\t\t\t\t\tconst element = document.querySelector(targetSelector);\n\t\t\t\t\treturn element !== null;\n\t\t\t\t});\n\n\t\t\t\tif (availableFeatures.length > 0) {\n\t\t\t\t\tsetAvailableMinorFeatures(availableFeatures);\n\t\t\t\t\t// Pass features directly to avoid async state issues\n\t\t\t\t\tshowMinorUpdateJoyride(availableFeatures[0], availableFeatures);\n\n\t\t\t\t\tif (observer) {\n\t\t\t\t\t\tobserver.disconnect();\n\t\t\t\t\t\tobserver = null;\n\t\t\t\t\t}\n\t\t\t\t\tif (scrollListener) {\n\t\t\t\t\t\twindow.removeEventListener('scroll', scrollListener);\n\t\t\t\t\t\tscrollListener = null;\n\t\t\t\t\t}\n\t\t\t\t\tif (checkTimeout) {\n\t\t\t\t\t\tclearTimeout(checkTimeout);\n\t\t\t\t\t\tcheckTimeout = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tobserver = new MutationObserver((mutations) => {\n\t\t\t\tlet shouldCheck = false;\n\t\t\t\tfor (const mutation of mutations) {\n\t\t\t\t\tif (mutation.type === 'childList' && mutation.addedNodes.length > 0) {\n\t\t\t\t\t\tfor (let i = 0; i < mutation.addedNodes.length; i++) {\n\t\t\t\t\t\t\tconst node = mutation.addedNodes[i];\n\t\t\t\t\t\t\tif (node.nodeType === Node.ELEMENT_NODE) {\n\t\t\t\t\t\t\t\tconst element = node as Element;\n\t\t\t\t\t\t\t\tif (element.id || element.querySelector('[id]')) {\n\t\t\t\t\t\t\t\t\tshouldCheck = true;\n\t\t\t\t\t\t\t\t\tbreak;\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}\n\t\t\t\t\tif (shouldCheck) break;\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\t!runJoyride &&\n\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\tshowMinorUpdates &&\n\t\t\t\t\tshouldCheck\n\t\t\t\t) {\n\t\t\t\t\tif (checkTimeout) {\n\t\t\t\t\t\tclearTimeout(checkTimeout);\n\t\t\t\t\t}\n\t\t\t\t\tcheckTimeout = setTimeout(() => {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\t\t\tshowMinorUpdates\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tcheckElementsAndStartTour();\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 200);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tscrollListener = () => {\n\t\t\t\tif (\n\t\t\t\t\t!runJoyride &&\n\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\tshowMinorUpdates\n\t\t\t\t) {\n\t\t\t\t\tif (checkTimeout) {\n\t\t\t\t\t\tclearTimeout(checkTimeout);\n\t\t\t\t\t}\n\t\t\t\t\t// Use RAF for smoother performance synced with browser paint\n\t\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\t\tcheckTimeout = setTimeout(() => {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\t\t\t\tshowMinorUpdates\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tcheckElementsAndStartTour();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, 300);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif (observer) {\n\t\t\t\tobserver.observe(document.body, {\n\t\t\t\t\tchildList: true,\n\t\t\t\t\tsubtree: true,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (scrollListener) {\n\t\t\t\twindow.addEventListener('scroll', scrollListener, { passive: true });\n\t\t\t}\n\n\t\t\tcheckElementsAndStartTour();\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (\n\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\tshowMinorUpdates\n\t\t\t\t) {\n\t\t\t\t\tcheckElementsAndStartTour();\n\t\t\t\t}\n\t\t\t}, 100);\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (\n\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\tshowMinorUpdates\n\t\t\t\t) {\n\t\t\t\t\tcheckElementsAndStartTour();\n\t\t\t\t}\n\t\t\t}, 1000);\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (\n\t\t\t\t\t!isCleanedUp &&\n\t\t\t\t\t!isProcessingMinorUpdate &&\n\t\t\t\t\t!currentMinorFeature &&\n\t\t\t\t\t!minorFeaturesSkipped &&\n\t\t\t\t\tshowMinorUpdates\n\t\t\t\t) {\n\t\t\t\t\tcheckElementsAndStartTour();\n\t\t\t\t}\n\t\t\t}, 500);\n\n\t\t\treturn () => {\n\t\t\t\tisCleanedUp = true;\n\t\t\t\tif (observer) {\n\t\t\t\t\tobserver.disconnect();\n\t\t\t\t}\n\t\t\t\tif (scrollListener) {\n\t\t\t\t\twindow.removeEventListener('scroll', scrollListener);\n\t\t\t\t}\n\t\t\t\tif (checkTimeout) {\n\t\t\t\t\tclearTimeout(checkTimeout);\n\t\t\t\t}\n\t\t\t};\n\t\t} else if (minorUpdateFeatures.length === 0 || isLoading) {\n\t\t\t// Don't clear joyride if we're in test mode with an active feature\n\t\t\tconst featureIdFromQuery = router?.query?.['featureId'] as string;\n\t\t\tconst isTestModeWithActiveFeature =\n\t\t\t\tfeatureIdFromQuery && currentMinorFeature;\n\n\t\t\tif (!isTestModeWithActiveFeature) {\n\t\t\t\tsetRunJoyride(false);\n\t\t\t\tsetJoyrideSteps([]);\n\t\t\t\tsetCurrentMinorFeature(null);\n\t\t\t\tsetAvailableMinorFeatures([]);\n\t\t\t\tsetMinorFeaturesSkipped(false);\n\t\t\t}\n\t\t}\n\t}, [\n\t\tminorUpdateFeatures,\n\t\tisLoading,\n\t\trunJoyride,\n\t\tisProcessingMinorUpdate,\n\t\tcurrentMinorFeature,\n\t\tminorFeaturesSkipped,\n\t\tshowMinorUpdates,\n\t\tmarkFeatureAsViewed,\n\t\tblockPopups,\n\t]);\n\n\tconst showMajorUpdateJoyride = (feature) => {\n\t\tsetCurrentMajorFeature(feature);\n\n\t\tconst currentIndex = majorUpdateFeatures.findIndex(\n\t\t\t(f) => f.id === feature.id,\n\t\t);\n\t\tconst totalFeatures = majorUpdateFeatures.length;\n\n\t\tconst majorSteps = [\n\t\t\t{\n\t\t\t\ttarget: SELECTORS.WHATS_NEW_BUTTON,\n\t\t\t\tcontent: (\n\t\t\t\t\t<MajorUpdatePopup\n\t\t\t\t\t\tfeature={feature}\n\t\t\t\t\t\tcurrentIndex={currentIndex}\n\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\tonSkip={() => handleSkipMajorUpdate(feature)}\n\t\t\t\t\t\tonExplore={(triggeredAction) =>\n\t\t\t\t\t\t\thandleExploreFeature(feature, triggeredAction)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tonPrevious={() => handlePreviousMajorUpdate(feature)}\n\t\t\t\t\t\tonNext={() => handleNextMajorUpdate(feature)}\n\t\t\t\t\t\tsetIsClosing={setIsClosingMajor}\n\t\t\t\t\t/>\n\t\t\t\t),\n\t\t\t\tplacement: 'bottom-start',\n\t\t\t\tplacementBeacon: 'top-end',\n\t\t\t\tdisableBeacon: true,\n\t\t\t\thideCloseButton: true,\n\t\t\t\thideSkipButton: true,\n\t\t\t\thideFooter: true,\n\t\t\t\toffset: 0,\n\t\t\t\tdata: { feature, isMajor: true },\n\t\t\t\tstyles: {\n\t\t\t\t\ttooltip: {\n\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\tborderRadius: '16px',\n\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t},\n\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t},\n\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\n\t\tsetMajorJoyrideSteps(majorSteps);\n\t\tsetRunMajorJoyride(true);\n\n\t\t// Fire announcement shown callback\n\t\tif (onAnnouncementShown && storeId) {\n\t\t\tonAnnouncementShown({\n\t\t\t\tstoreId,\n\t\t\t\tannouncementId: feature.id,\n\t\t\t\tannouncementTitle: feature.title,\n\t\t\t\timageUrl: feature.displayImage || feature.image,\n\t\t\t\tvideoUrl: feature.productVideo,\n\t\t\t});\n\t\t}\n\t};\n\n\tconst handleSkipMajorUpdate = useCallback(\n\t\tasync (feature) => {\n\t\t\tconst targetFeature = feature || currentMajorFeature;\n\n\t\t\tif (targetFeature) {\n\t\t\t\tsetIsProcessingMajorUpdate(true);\n\n\t\t\t\tawait Promise.all(\n\t\t\t\t\tmajorUpdateFeatures.map((majorFeature) =>\n\t\t\t\t\t\tmarkFeatureAsViewed(majorFeature.id),\n\t\t\t\t\t),\n\t\t\t\t);\n\n\t\t\t\tsetRunMajorJoyride(false);\n\t\t\t\tsetCurrentMajorFeature(null);\n\t\t\t\tsetMajorJoyrideSteps([]);\n\n\t\t\t\tsetShowMinorUpdates(true);\n\n\t\t\t\t// Fire announcement interacted callback for Skip\n\t\t\t\tif (onAnnouncementInteracted && storeId) {\n\t\t\t\t\tonAnnouncementInteracted({\n\t\t\t\t\t\tstoreId,\n\t\t\t\t\t\tannouncementId: targetFeature.id,\n\t\t\t\t\t\tannouncementTitle: targetFeature.title,\n\t\t\t\t\t\timageUrl: targetFeature.displayImage || targetFeature.image,\n\t\t\t\t\t\tvideoUrl: targetFeature.productVideo,\n\t\t\t\t\t\tbuttonClicked: 'Skip',\n\t\t\t\t\t\tbuttonName: 'Skip',\n\t\t\t\t\t\tbuttonUrl: undefined,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsetIsProcessingMajorUpdate(false);\n\t\t\t\t}, 500);\n\t\t\t} else {\n\t\t\t\t// do nothing\n\t\t\t}\n\t\t},\n\t\t[currentMajorFeature, majorUpdateFeatures, markFeatureAsViewed],\n\t);\n\n\tconst handleExploreFeature = useCallback(\n\t\tasync (feature, triggeredAction?: string) => {\n\t\t\tsetIsProcessingMajorUpdate(true);\n\t\t\t// Await so the feature is marked before any page navigation\n\t\t\tawait markFeatureAsViewed(feature.id);\n\t\t\tconst action = triggeredAction ?? feature.primaryButton?.action;\n\t\t\tif (action === 'Play Video' && feature.productVideo) {\n\t\t\t\tsetVideoUrl(feature.productVideo);\n\t\t\t\tsetIsVideoModalOpen(true);\n\t\t\t\tsetBlockPopups(true);\n\t\t\t}\n\n\t\t\tif (action === 'Open link') {\n\t\t\t\tconst url =\n\t\t\t\t\tfeature.primaryButton?.redirectionUrl || feature.redirectUrl;\n\t\t\t\tif (url && !url.startsWith('http')) {\n\t\t\t\t\twindow.location.href = url;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsetRunMajorJoyride(false);\n\t\t\tsetCurrentMajorFeature(null);\n\t\t\tsetMajorJoyrideSteps([]);\n\t\t\tconst currentIndex = majorUpdateFeatures.findIndex(\n\t\t\t\t(f) => f.id === feature.id,\n\t\t\t);\n\t\t\tconst isLastMajorUpdate = currentIndex === majorUpdateFeatures.length - 1;\n\t\t\tif (isLastMajorUpdate) {\n\t\t\t\tsetShowMinorUpdates(true);\n\t\t\t}\n\n\t\t\t// Fire announcement interacted callback for Primary button\n\t\t\tif (onAnnouncementInteracted && storeId) {\n\t\t\t\tonAnnouncementInteracted({\n\t\t\t\t\tstoreId,\n\t\t\t\t\tannouncementId: feature.id,\n\t\t\t\t\tannouncementTitle: feature.title,\n\t\t\t\t\timageUrl: feature.displayImage || feature.image,\n\t\t\t\t\tvideoUrl: feature.productVideo,\n\t\t\t\t\tbuttonClicked: 'Primary',\n\t\t\t\t\tbuttonName: feature.buttonText || 'Explore',\n\t\t\t\t\tbuttonUrl: feature.redirectUrl || feature.productVideo,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tsetIsProcessingMajorUpdate(false);\n\t\t\t}, 500);\n\t\t},\n\t\t[majorUpdateFeatures, markFeatureAsViewed],\n\t);\n\n\tconst handlePreviousMajorUpdate = useCallback(\n\t\t(feature) => {\n\t\t\tconst targetFeature = feature || currentMajorFeature;\n\n\t\t\tif (!targetFeature) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst currentIndex = majorUpdateFeatures.findIndex(\n\t\t\t\t(f) => f.id === targetFeature.id,\n\t\t\t);\n\n\t\t\tif (currentIndex > 0) {\n\t\t\t\tconst prevFeature = majorUpdateFeatures[currentIndex - 1];\n\t\t\t\tsetCurrentMajorFeature(prevFeature);\n\n\t\t\t\tconst prevIndex = currentIndex - 1;\n\t\t\t\tconst totalFeatures = majorUpdateFeatures.length;\n\n\t\t\t\tconst updatedSteps = [\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget: '[data-testid=\"whats-new-button\"]',\n\t\t\t\t\t\tcontent: (\n\t\t\t\t\t\t\t<MajorUpdatePopup\n\t\t\t\t\t\t\t\tfeature={prevFeature}\n\t\t\t\t\t\t\t\tcurrentIndex={prevIndex}\n\t\t\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\t\t\tonSkip={() => handleSkipMajorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tonExplore={(triggeredAction) =>\n\t\t\t\t\t\t\t\t\thandleExploreFeature(prevFeature, triggeredAction)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tonPrevious={() => handlePreviousMajorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tonNext={() => handleNextMajorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tsetIsClosing={setIsClosingMajor}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t\tplacement: 'bottom-start',\n\t\t\t\t\t\tplacementBeacon: 'top-end',\n\t\t\t\t\t\tdisableBeacon: true,\n\t\t\t\t\t\thideCloseButton: true,\n\t\t\t\t\t\thideSkipButton: true,\n\t\t\t\t\t\thideFooter: true,\n\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\tdata: { feature: prevFeature, isMajor: true },\n\t\t\t\t\t\tstyles: {\n\t\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\tborderRadius: '16px',\n\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t];\n\n\t\t\t\tsetMajorJoyrideSteps(updatedSteps);\n\t\t\t} else {\n\t\t\t\t// do nothing\n\t\t\t}\n\t\t},\n\t\t[currentMajorFeature, majorUpdateFeatures],\n\t);\n\n\tconst handleNextMajorUpdate = useCallback(\n\t\t(feature) => {\n\t\t\tconst targetFeature = feature || currentMajorFeature;\n\n\t\t\tif (!targetFeature) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst currentIndex = majorUpdateFeatures.findIndex(\n\t\t\t\t(f) => f.id === targetFeature.id,\n\t\t\t);\n\n\t\t\tif (currentIndex < majorUpdateFeatures.length - 1) {\n\t\t\t\tconst nextFeature = majorUpdateFeatures[currentIndex + 1];\n\t\t\t\tsetCurrentMajorFeature(nextFeature);\n\n\t\t\t\tconst nextIndex = currentIndex + 1;\n\t\t\t\tconst totalFeatures = majorUpdateFeatures.length;\n\n\t\t\t\tconst updatedSteps = [\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget: '[data-testid=\"whats-new-button\"]',\n\t\t\t\t\t\tcontent: (\n\t\t\t\t\t\t\t<MajorUpdatePopup\n\t\t\t\t\t\t\t\tfeature={nextFeature}\n\t\t\t\t\t\t\t\tcurrentIndex={nextIndex}\n\t\t\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\t\t\tonSkip={() => handleSkipMajorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tonExplore={(triggeredAction) =>\n\t\t\t\t\t\t\t\t\thandleExploreFeature(nextFeature, triggeredAction)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tonPrevious={() => handlePreviousMajorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tonNext={() => handleNextMajorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tsetIsClosing={setIsClosingMajor}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t\tplacement: 'bottom-start',\n\t\t\t\t\t\tplacementBeacon: 'top-end',\n\t\t\t\t\t\tdisableBeacon: true,\n\t\t\t\t\t\thideCloseButton: true,\n\t\t\t\t\t\thideSkipButton: true,\n\t\t\t\t\t\thideFooter: true,\n\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\tdata: { feature: nextFeature, isMajor: true },\n\t\t\t\t\t\tstyles: {\n\t\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\tborderRadius: '16px',\n\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t];\n\n\t\t\t\tsetMajorJoyrideSteps(updatedSteps);\n\t\t\t} else {\n\t\t\t\tsetIsProcessingMajorUpdate(true);\n\n\t\t\t\tmarkFeatureAsViewed(targetFeature.id);\n\t\t\t\tsetRunMajorJoyride(false);\n\t\t\t\tsetCurrentMajorFeature(null);\n\t\t\t\tsetMajorJoyrideSteps([]);\n\n\t\t\t\tsetShowMinorUpdates(true);\n\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsetIsProcessingMajorUpdate(false);\n\t\t\t\t}, 500);\n\t\t\t}\n\t\t},\n\t\t[currentMajorFeature, majorUpdateFeatures, markFeatureAsViewed],\n\t);\n\n\tconst showMajorUpdatePopup = () => {\n\t\tif (majorUpdateFeatures.length > 0 && !currentMajorFeature) {\n\t\t\tconst whatsNewButton = document.querySelector(\n\t\t\t\t'[data-testid=\"whats-new-button\"]',\n\t\t\t);\n\n\t\t\tif (whatsNewButton) {\n\t\t\t\tshowMajorUpdateJoyride(majorUpdateFeatures[0]);\n\t\t\t}\n\t\t}\n\t};\n\n\tuseEffect(() => {\n\t\t(window as any).showMajorUpdatePopup = showMajorUpdatePopup;\n\t\treturn () => {\n\t\t\tdelete (window as any).showMajorUpdatePopup;\n\t\t};\n\t}, [majorUpdateFeatures, currentMajorFeature]);\n\tconst handleMajorJoyrideCallback = useCallback(\n\t\t(data) => {\n\t\t\tconst { action } = data;\n\n\t\t\tif (action === ACTIONS.CLOSE) {\n\t\t\t\tif (currentMajorFeature) {\n\t\t\t\t\tsetIsProcessingMajorUpdate(true);\n\n\t\t\t\t\tmajorUpdateFeatures.forEach((majorFeature) => {\n\t\t\t\t\t\tmarkFeatureAsViewed(majorFeature.id);\n\t\t\t\t\t});\n\n\t\t\t\t\tsetShowMinorUpdates(true);\n\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tsetIsProcessingMajorUpdate(false);\n\t\t\t\t\t}, 500);\n\t\t\t\t}\n\n\t\t\t\tsetRunMajorJoyride(false);\n\t\t\t\tsetCurrentMajorFeature(null);\n\t\t\t\tsetMajorJoyrideSteps([]);\n\t\t\t}\n\t\t},\n\t\t[currentMajorFeature, majorUpdateFeatures, markFeatureAsViewed],\n\t);\n\n\tconst handleMinorJoyrideCallback = useCallback(\n\t\t(data) => {\n\t\t\tconst { action } = data;\n\n\t\t\tif (action === ACTIONS.CLOSE) {\n\t\t\t\tif (currentMinorFeature) {\n\t\t\t\t\tsetIsProcessingMinorUpdate(true);\n\n\t\t\t\t\t// Only mark the current feature as viewed, not all features\n\t\t\t\t\tmarkFeatureAsViewed(currentMinorFeature.id);\n\n\t\t\t\t\t// Check if there are more features to show\n\t\t\t\t\tconst currentIndex = availableMinorFeatures.findIndex(\n\t\t\t\t\t\t(f) => f.id === currentMinorFeature.id,\n\t\t\t\t\t);\n\t\t\t\t\tconst isLastFeature =\n\t\t\t\t\t\tcurrentIndex === availableMinorFeatures.length - 1;\n\n\t\t\t\t\tif (isLastFeature) {\n\t\t\t\t\t\t// Only skip remaining features if this was the last one\n\t\t\t\t\t\tsetMinorFeaturesSkipped(true);\n\t\t\t\t\t}\n\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tsetIsProcessingMinorUpdate(false);\n\t\t\t\t\t}, 500);\n\t\t\t\t}\n\n\t\t\t\tsetRunJoyride(false);\n\t\t\t\tsetCurrentMinorFeature(null);\n\t\t\t\tsetJoyrideSteps([]);\n\t\t\t}\n\t\t},\n\t\t[currentMinorFeature, availableMinorFeatures, markFeatureAsViewed],\n\t);\n\tconst showMinorUpdateJoyride = async (feature, featuresToUse?) => {\n\t\tsetCurrentMinorFeature(feature);\n\n\t\t// Use provided features array or fall back to state (for test mode)\n\t\tconst features = featuresToUse || availableMinorFeatures;\n\t\tconst currentIndex = features.findIndex((f) => f.id === feature.id);\n\t\tconst totalFeatures = features.length;\n\n\t\tconst targetSelector =\n\t\t\tfeature.featureTag.startsWith('#') ||\n\t\t\tfeature.featureTag.startsWith('.') ||\n\t\t\tfeature.featureTag.startsWith('[')\n\t\t\t\t? feature.featureTag\n\t\t\t\t: `#${feature.featureTag}`;\n\n\t\t// Scroll to target element smoothly before showing popup\n\t\tconst targetElement = document.querySelector(targetSelector);\n\t\tif (targetElement) {\n\t\t\ttry {\n\t\t\t\t// Dynamically import to avoid circular dependencies\n\t\t\t\tconst { scrollToElementSmooth } = await import(\n\t\t\t\t\t'./utils/elementHelpers'\n\t\t\t\t);\n\t\t\t\tawait scrollToElementSmooth(targetElement, 120);\n\t\t\t} catch (error) {\n\t\t\t\t// Scroll failed silently\n\t\t\t}\n\t\t}\n\n\t\tconst minorSteps = [\n\t\t\t{\n\t\t\t\ttarget: targetSelector,\n\t\t\t\tcontent: (\n\t\t\t\t\t<MinorUpdatePopup\n\t\t\t\t\t\tfeature={feature}\n\t\t\t\t\t\tcurrentIndex={currentIndex}\n\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\tonSkip={() => handleSkipMinorUpdate(feature)}\n\t\t\t\t\t\tonExplore={(triggeredAction) =>\n\t\t\t\t\t\t\thandleExploreMinorFeature(feature, triggeredAction)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tonPrevious={() => handlePreviousMinorUpdate(feature)}\n\t\t\t\t\t\tonNext={() => handleNextMinorUpdate(feature)}\n\t\t\t\t\t\tsetIsClosing={setIsClosingMinor}\n\t\t\t\t\t/>\n\t\t\t\t),\n\t\t\t\tplacement: 'bottom',\n\t\t\t\tplacementBeacon: 'bottom-end',\n\t\t\t\tdisableBeacon: true,\n\t\t\t\thideCloseButton: true,\n\t\t\t\thideSkipButton: true,\n\t\t\t\thideFooter: true,\n\t\t\t\toffset: 0,\n\t\t\t\tdata: { feature, isMinor: true },\n\t\t\t\tstyles: {\n\t\t\t\t\ttooltip: {\n\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t},\n\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t},\n\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\t\tsetJoyrideSteps(minorSteps);\n\t\tsetRunJoyride(true);\n\t};\n\n\tconst handleSkipMinorUpdate = useCallback(\n\t\tasync (feature) => {\n\t\t\tconst targetFeature = feature || currentMinorFeature;\n\n\t\t\tif (targetFeature) {\n\t\t\t\tsetIsProcessingMinorUpdate(true);\n\n\t\t\t\t// Only mark the current feature as viewed, not all features\n\t\t\t\tawait markFeatureAsViewed(targetFeature.id);\n\n\t\t\t\t// Add to session tracker to prevent re-showing\n\t\t\t\tsetShownMinorFeatureIds((prev) => new Set(prev).add(targetFeature.id));\n\n\t\t\t\tsetRunJoyride(false);\n\t\t\t\tsetCurrentMinorFeature(null);\n\t\t\t\tsetJoyrideSteps([]);\n\n\t\t\t\t// Find next unshown feature\n\t\t\t\tconst nextFeature = availableMinorFeatures.find(\n\t\t\t\t\t(f) => f.id !== targetFeature.id && !shownMinorFeatureIds.has(f.id),\n\t\t\t\t);\n\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsetIsProcessingMinorUpdate(false);\n\n\t\t\t\t\tif (nextFeature) {\n\t\t\t\t\t\t// Auto-advance to next feature\n\t\t\t\t\t\tshowMinorUpdateJoyride(nextFeature, availableMinorFeatures);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// No more features to show\n\t\t\t\t\t\tsetMinorFeaturesSkipped(true);\n\t\t\t\t\t}\n\t\t\t\t}, 500);\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\tcurrentMinorFeature,\n\t\t\tavailableMinorFeatures,\n\t\t\tmarkFeatureAsViewed,\n\t\t\tshownMinorFeatureIds,\n\t\t],\n\t);\n\n\tconst handleExploreMinorFeature = useCallback(\n\t\tasync (feature, triggeredAction?: string) => {\n\t\t\tsetIsProcessingMinorUpdate(true);\n\n\t\t\t// Only mark the current feature as viewed\n\t\t\t// Await so the feature is marked before any page navigation\n\t\t\tawait markFeatureAsViewed(feature.id);\n\n\t\t\t// Add to session tracker to prevent re-showing\n\t\t\tsetShownMinorFeatureIds((prev) => new Set(prev).add(feature.id));\n\n\t\t\tconst action = triggeredAction ?? feature.primaryButton?.action;\n\n\t\t\tif (action === 'Play Video' && feature.productVideo) {\n\t\t\t\tsetVideoUrl(feature.productVideo);\n\t\t\t\tsetIsVideoModalOpen(true);\n\t\t\t\tsetBlockPopups(true);\n\t\t\t}\n\n\t\t\tif (action === 'Open link') {\n\t\t\t\tconst url =\n\t\t\t\t\tfeature.primaryButton?.redirectionUrl || feature.redirectUrl;\n\t\t\t\tif (url && !url.startsWith('http')) {\n\t\t\t\t\twindow.location.href = url;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsetRunJoyride(false);\n\t\t\tsetCurrentMinorFeature(null);\n\t\t\tsetJoyrideSteps([]);\n\n\t\t\t// Find next unshown feature (only auto-advance if no video modal)\n\t\t\tconst nextFeature = availableMinorFeatures.find(\n\t\t\t\t(f) => f.id !== feature.id && !shownMinorFeatureIds.has(f.id),\n\t\t\t);\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tsetIsProcessingMinorUpdate(false);\n\n\t\t\t\t// Only auto-advance if no video modal is opened\n\t\t\t\tif (nextFeature && action !== 'Play Video') {\n\t\t\t\t\t// Auto-advance to next feature\n\t\t\t\t\tshowMinorUpdateJoyride(nextFeature, availableMinorFeatures);\n\t\t\t\t} else if (!nextFeature) {\n\t\t\t\t\t// No more features to show\n\t\t\t\t\tsetMinorFeaturesSkipped(true);\n\t\t\t\t}\n\t\t\t\t// If video modal opened, wait for user to close it before advancing\n\t\t\t}, 500);\n\t\t},\n\t\t[availableMinorFeatures, markFeatureAsViewed, shownMinorFeatureIds],\n\t);\n\n\tconst handlePreviousMinorUpdate = useCallback(\n\t\tasync (feature) => {\n\t\t\tconst targetFeature = feature || currentMinorFeature;\n\n\t\t\tif (!targetFeature) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst currentIndex = availableMinorFeatures.findIndex(\n\t\t\t\t(f) => f.id === targetFeature.id,\n\t\t\t);\n\n\t\t\tif (currentIndex > 0) {\n\t\t\t\tconst prevFeature = availableMinorFeatures[currentIndex - 1];\n\t\t\t\tsetCurrentMinorFeature(prevFeature);\n\n\t\t\t\tconst targetSelector =\n\t\t\t\t\tprevFeature.featureTag.startsWith('#') ||\n\t\t\t\t\tprevFeature.featureTag.startsWith('.') ||\n\t\t\t\t\tprevFeature.featureTag.startsWith('[')\n\t\t\t\t\t\t? prevFeature.featureTag\n\t\t\t\t\t\t: `#${prevFeature.featureTag}`;\n\n\t\t\t\t// Scroll to the previous feature element\n\t\t\t\tconst targetElement = document.querySelector(targetSelector);\n\t\t\t\tif (targetElement) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst { scrollToElementSmooth } = await import(\n\t\t\t\t\t\t\t'./utils/elementHelpers'\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait scrollToElementSmooth(targetElement, 120);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t// Scroll failed silently\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst prevIndex = currentIndex - 1;\n\t\t\t\tconst totalFeatures = availableMinorFeatures.length;\n\n\t\t\t\tconst updatedSteps = [\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget: targetSelector,\n\t\t\t\t\t\tcontent: (\n\t\t\t\t\t\t\t<MinorUpdatePopup\n\t\t\t\t\t\t\t\tfeature={prevFeature}\n\t\t\t\t\t\t\t\tcurrentIndex={prevIndex}\n\t\t\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\t\t\tonSkip={() => handleSkipMinorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tonExplore={(triggeredAction) =>\n\t\t\t\t\t\t\t\t\thandleExploreMinorFeature(prevFeature, triggeredAction)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tonPrevious={() => handlePreviousMinorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tonNext={() => handleNextMinorUpdate(prevFeature)}\n\t\t\t\t\t\t\t\tsetIsClosing={setIsClosingMinor}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t\tplacement: 'bottom',\n\t\t\t\t\t\tplacementBeacon: 'bottom-end',\n\t\t\t\t\t\tdisableBeacon: true,\n\t\t\t\t\t\thideCloseButton: true,\n\t\t\t\t\t\thideSkipButton: true,\n\t\t\t\t\t\thideFooter: true,\n\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\tdata: { feature: prevFeature, isMinor: true },\n\t\t\t\t\t\tstyles: {\n\t\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t];\n\n\t\t\t\tsetJoyrideSteps(updatedSteps);\n\t\t\t}\n\t\t},\n\t\t[currentMinorFeature, availableMinorFeatures],\n\t);\n\n\tconst handleNextMinorUpdate = useCallback(\n\t\tasync (feature) => {\n\t\t\tconst targetFeature = feature || currentMinorFeature;\n\n\t\t\tif (!targetFeature) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst currentIndex = availableMinorFeatures.findIndex(\n\t\t\t\t(f) => f.id === targetFeature.id,\n\t\t\t);\n\n\t\t\tif (currentIndex < availableMinorFeatures.length - 1) {\n\t\t\t\tconst nextFeature = availableMinorFeatures[currentIndex + 1];\n\t\t\t\tsetCurrentMinorFeature(nextFeature);\n\n\t\t\t\tconst targetSelector =\n\t\t\t\t\tnextFeature.featureTag.startsWith('#') ||\n\t\t\t\t\tnextFeature.featureTag.startsWith('.') ||\n\t\t\t\t\tnextFeature.featureTag.startsWith('[')\n\t\t\t\t\t\t? nextFeature.featureTag\n\t\t\t\t\t\t: `#${nextFeature.featureTag}`;\n\n\t\t\t\t// Scroll to the next feature element\n\t\t\t\tconst targetElement = document.querySelector(targetSelector);\n\t\t\t\tif (targetElement) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst { scrollToElementSmooth } = await import(\n\t\t\t\t\t\t\t'./utils/elementHelpers'\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait scrollToElementSmooth(targetElement, 120);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t// Scroll failed silently\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst nextIndex = currentIndex + 1;\n\t\t\t\tconst totalFeatures = availableMinorFeatures.length;\n\n\t\t\t\tconst updatedSteps = [\n\t\t\t\t\t{\n\t\t\t\t\t\ttarget: targetSelector,\n\t\t\t\t\t\tcontent: (\n\t\t\t\t\t\t\t<MinorUpdatePopup\n\t\t\t\t\t\t\t\tfeature={nextFeature}\n\t\t\t\t\t\t\t\tcurrentIndex={nextIndex}\n\t\t\t\t\t\t\t\ttotalFeatures={totalFeatures}\n\t\t\t\t\t\t\t\tonSkip={() => handleSkipMinorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tonExplore={(triggeredAction) =>\n\t\t\t\t\t\t\t\t\thandleExploreMinorFeature(nextFeature, triggeredAction)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tonPrevious={() => handlePreviousMinorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tonNext={() => handleNextMinorUpdate(nextFeature)}\n\t\t\t\t\t\t\t\tsetIsClosing={setIsClosingMinor}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t),\n\t\t\t\t\t\tplacement: 'bottom',\n\t\t\t\t\t\tplacementBeacon: 'bottom-end',\n\t\t\t\t\t\tdisableBeacon: true,\n\t\t\t\t\t\thideCloseButton: true,\n\t\t\t\t\t\thideSkipButton: true,\n\t\t\t\t\t\thideFooter: true,\n\t\t\t\t\t\toffset: 0,\n\t\t\t\t\t\tdata: { feature: nextFeature, isMinor: true },\n\t\t\t\t\t\tstyles: {\n\t\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t];\n\n\t\t\t\tsetJoyrideSteps(updatedSteps);\n\t\t\t} else {\n\t\t\t\tsetIsProcessingMinorUpdate(true);\n\t\t\t\tsetMinorFeaturesSkipped(true);\n\n\t\t\t\tmarkFeatureAsViewed(targetFeature.id);\n\t\t\t\tsetRunJoyride(false);\n\t\t\t\tsetCurrentMinorFeature(null);\n\t\t\t\tsetJoyrideSteps([]);\n\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tsetIsProcessingMinorUpdate(false);\n\t\t\t\t}, 500);\n\t\t\t}\n\t\t},\n\t\t[currentMinorFeature, availableMinorFeatures, markFeatureAsViewed],\n\t);\n\n\treturn (\n\t\t<>\n\t\t\t{children}\n\n\t\t\t{majorJoyrideSteps.length > 0 && (\n\t\t\t\t<Joyride\n\t\t\t\t\tkey={`major-joyride-${majorJoyrideKey}`}\n\t\t\t\t\tsteps={majorJoyrideSteps}\n\t\t\t\t\trun={runMajorJoyride}\n\t\t\t\t\tcontinuous={false}\n\t\t\t\t\tshowProgress={false}\n\t\t\t\t\tshowSkipButton={false}\n\t\t\t\t\tcallback={handleMajorJoyrideCallback}\n\t\t\t\t\tdisableOverlayClose={false}\n\t\t\t\t\tdisableCloseOnEsc={false}\n\t\t\t\t\tdisableOverlay={false}\n\t\t\t\t\tspotlightClicks={false}\n\t\t\t\t\tstyles={{\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tprimaryColor: '#007bff',\n\t\t\t\t\t\t\tzIndex: 10000,\n\t\t\t\t\t\t\twidth: 'auto',\n\t\t\t\t\t\t\tarrowColor: isClosingMajor ? 'transparent' : '#212121',\n\t\t\t\t\t\t},\n\t\t\t\t\t\toverlay: {\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tspotlight: {\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\tborderRadius: '16px',\n\t\t\t\t\t\t\tfontSize: '14px',\n\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t}}\n\t\t\t\t\tlocale={{\n\t\t\t\t\t\tback: 'Back',\n\t\t\t\t\t\tclose: 'Close',\n\t\t\t\t\t\tlast: 'Close',\n\t\t\t\t\t\tnext: 'Next',\n\t\t\t\t\t\tskip: 'Skip',\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{joyrideSteps.length > 0 && (\n\t\t\t\t<Joyride\n\t\t\t\t\tkey={`minor-joyride-${minorJoyrideKey}`}\n\t\t\t\t\tsteps={joyrideSteps}\n\t\t\t\t\trun={runJoyride}\n\t\t\t\t\tcontinuous={false}\n\t\t\t\t\tshowProgress={false}\n\t\t\t\t\tshowSkipButton={false}\n\t\t\t\t\tcallback={handleMinorJoyrideCallback}\n\t\t\t\t\tdisableOverlayClose={false}\n\t\t\t\t\tdisableCloseOnEsc={false}\n\t\t\t\t\tdisableOverlay={false}\n\t\t\t\t\tscrollToFirstStep={true}\n\t\t\t\t\tscrollOffset={120}\n\t\t\t\t\tdisableScrolling={false}\n\t\t\t\t\tstyles={{\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tprimaryColor: '#007bff',\n\t\t\t\t\t\t\tzIndex: 10000,\n\t\t\t\t\t\t\twidth: 'auto',\n\t\t\t\t\t\t\tarrowColor: isClosingMinor ? 'transparent' : '#ffffff',\n\t\t\t\t\t\t},\n\t\t\t\t\t\toverlay: {\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tspotlight: {\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\tborderRadius: '8px',\n\t\t\t\t\t\t\tboxShadow: isClosingMinor\n\t\t\t\t\t\t\t\t? 'none'\n\t\t\t\t\t\t\t\t: '0 0 0 9999px rgba(0, 0, 0, 0.4), 0 0 0 3px rgba(255, 255, 255, 0.8), 0 0 20px 8px rgba(255, 255, 255, 0.4)',\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttooltip: {\n\t\t\t\t\t\t\tborderRadius: '4px',\n\t\t\t\t\t\t\tfontSize: '14px',\n\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t\tbackgroundColor: 'transparent',\n\t\t\t\t\t\t\tborder: 'none',\n\t\t\t\t\t\t\tfilter: 'none',\n\t\t\t\t\t\t\tboxShadow: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttooltipContent: {\n\t\t\t\t\t\t\tpadding: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonNext: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonBack: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonSkip: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbuttonClose: {\n\t\t\t\t\t\t\tdisplay: 'none',\n\t\t\t\t\t\t},\n\t\t\t\t\t}}\n\t\t\t\t\tlocale={{\n\t\t\t\t\t\tback: 'Back',\n\t\t\t\t\t\tclose: 'Close',\n\t\t\t\t\t\tlast: 'Close',\n\t\t\t\t\t\tnext: 'Next',\n\t\t\t\t\t\tskip: 'Skip',\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t<VideoModal\n\t\t\t\tisOpen={isVideoModalOpen}\n\t\t\t\tvideoUrl={videoUrl}\n\t\t\t\tonClose={() => {\n\t\t\t\t\tsetIsVideoModalOpen(false);\n\t\t\t\t\tsetVideoUrl('');\n\t\t\t\t\tsetBlockPopups(false);\n\n\t\t\t\t\t// After video modal closes, check if there are more features to show\n\t\t\t\t\tconst nextFeature = availableMinorFeatures.find(\n\t\t\t\t\t\t(f) => !shownMinorFeatureIds.has(f.id),\n\t\t\t\t\t);\n\n\t\t\t\t\tif (nextFeature) {\n\t\t\t\t\t\t// Auto-advance to next feature after video\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\tshowMinorUpdateJoyride(nextFeature, availableMinorFeatures);\n\t\t\t\t\t\t}, 300);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// No more features to show\n\t\t\t\t\t\tsetMinorFeaturesSkipped(true);\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t/>\n\t\t</>\n\t);\n};\n\nexport default FeatureAnnouncementProvider;\n"],"names":["FeatureAnnouncementProvider","_ref","children","fetchVisibleFeatures","getStoreFeatureProgress","fetchFeatureById","markFeatureAsViewedForStore","isFeatureApplicableToCurrentPage","module","router","storeId","onAnnouncementShown","onAnnouncementInteracted","majorUpdateFeatures","minorUpdateFeatures","isLoading","markFeatureAsViewed","useFeatureAnnouncements","currentMajorFeature","setCurrentMajorFeature","useState","currentMinorFeature","setCurrentMinorFeature","runJoyride","setRunJoyride","joyrideSteps","setJoyrideSteps","runMajorJoyride","setRunMajorJoyride","majorJoyrideSteps","setMajorJoyrideSteps","isProcessingMajorUpdate","setIsProcessingMajorUpdate","isProcessingMinorUpdate","setIsProcessingMinorUpdate","availableMinorFeatures","setAvailableMinorFeatures","minorFeaturesSkipped","setMinorFeaturesSkipped","showMinorUpdates","setShowMinorUpdates","isVideoModalOpen","setIsVideoModalOpen","videoUrl","setVideoUrl","blockPopups","setBlockPopups","isClosingMajor","setIsClosingMajor","isClosingMinor","setIsClosingMinor","majorJoyrideKey","setMajorJoyrideKey","minorJoyrideKey","setMinorJoyrideKey","shownMinorFeatureIds","setShownMinorFeatureIds","Set","useEffect","styleId","styleElement","document","getElementById","createElement","id","head","appendChild","textContent","el","remove","prev","pathname","length","attempts","MAX_ATTEMPTS","checkWhatsNewButton","querySelector","showMajorUpdateJoyride","setTimeout","featureIdFromQuery","_a","query","forcedFeature","find","f","featureTag","interval","setInterval","targetSelector","startsWith","testModeFeatures","showMinorUpdateJoyride","clearInterval","observer","scrollListener","checkTimeout","isCleanedUp","checkElementsAndStartTour","availableFeatures","filter","feature","trim","has","disconnect","window","removeEventListener","clearTimeout","MutationObserver","mutations","shouldCheck","mutation","type","addedNodes","i","node","nodeType","Node","ELEMENT_NODE","element","requestAnimationFrame","observe","body","childList","subtree","addEventListener","passive","currentIndex","findIndex","totalFeatures","majorSteps","target","SELECTORS","WHATS_NEW_BUTTON","content","_jsx","MajorUpdatePopup","onSkip","handleSkipMajorUpdate","onExplore","triggeredAction","handleExploreFeature","onPrevious","handlePreviousMajorUpdate","onNext","handleNextMajorUpdate","setIsClosing","placement","placementBeacon","disableBeacon","hideCloseButton","hideSkipButton","hideFooter","offset","data","isMajor","styles","tooltip","padding","backgroundColor","borderRadius","border","boxShadow","tooltipContent","buttonNext","display","buttonBack","buttonClose","buttonSkip","announcementId","announcementTitle","title","imageUrl","displayImage","image","productVideo","useCallback","__awaiter","targetFeature","Promise","all","map","majorFeature","buttonClicked","buttonName","buttonUrl","undefined","action","_b","primaryButton","url","_c","redirectionUrl","redirectUrl","location","href","buttonText","prevFeature","prevIndex","updatedSteps","nextFeature","nextIndex","showMajorUpdatePopup","handleMajorJoyrideCallback","ACTIONS","CLOSE","forEach","handleMinorJoyrideCallback","featuresToUse","features","targetElement","scrollToElementSmooth","import","error","minorSteps","MinorUpdatePopup","handleSkipMinorUpdate","handleExploreMinorFeature","handlePreviousMinorUpdate","handleNextMinorUpdate","isMinor","add","_d","_e","_jsxs","_Fragment","Joyride","steps","run","continuous","showProgress","showSkipButton","callback","disableOverlayClose","disableCloseOnEsc","disableOverlay","spotlightClicks","options","primaryColor","zIndex","width","arrowColor","overlay","spotlight","fontSize","locale","back","close","last","next","skip","scrollToFirstStep","scrollOffset","disableScrolling","VideoModal","isOpen","onClose"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{Extension as t}from"../../../node_modules/@tiptap/core/dist/index.js";const o=t.create({name:"sendShortcut",addOptions:()=>({onSend:void 0,sendShortcut:void 0,extraShortcuts:[]}),addKeyboardShortcuts(){var t,o;const i={};if(this.options.onSend&&this.options.sendShortcut){const o=Array.isArray(this.options.sendShortcut)?this.options.sendShortcut:[this.options.sendShortcut],e=()=>{var t,o,i;return this.options.onSend({html:this.editor.getHTML(),text:this.editor.getText(),isEmpty:this.editor.isEmpty,characterCount:null!==(i=null===(o=null===(t=this.editor.storage.characterCount)||void 0===t?void 0:t.characters)||void 0===o?void 0:o.call(t))&&void 0!==i?i:this.editor.getText().length}),!0};for(const r of o){i[[...(null!==(t=r.modifiers)&&void 0!==t?t:[]).map((t=>"mod"===t?"Mod":t.charAt(0).toUpperCase()+t.slice(1))),r.key].join("-")]=e}}for(const t of this.options.extraShortcuts){i[[...(null!==(o=t.modifiers)&&void 0!==o?o:[]).map((t=>"mod"===t?"Mod":t.charAt(0).toUpperCase()+t.slice(1))),t.key].join("-")]=()=>(t.handler(),!0)}return i}});export{o as SendShortcutExtension};
1
+ import{Extension as o}from"../../../node_modules/@tiptap/core/dist/index.js";import{extractContent as t}from"../../BikEditor.utils.js";const s=o.create({name:"sendShortcut",addOptions:()=>({onSend:void 0,sendShortcut:void 0,extraShortcuts:[]}),addKeyboardShortcuts(){var o,s;const i={};if(this.options.onSend&&this.options.sendShortcut){const s=Array.isArray(this.options.sendShortcut)?this.options.sendShortcut:[this.options.sendShortcut],r=()=>(this.options.onSend(t(this.editor)),!0);for(const t of s){i[[...(null!==(o=t.modifiers)&&void 0!==o?o:[]).map((o=>"mod"===o?"Mod":o.charAt(0).toUpperCase()+o.slice(1))),t.key].join("-")]=r}}for(const o of this.options.extraShortcuts){i[[...(null!==(s=o.modifiers)&&void 0!==s?s:[]).map((o=>"mod"===o?"Mod":o.charAt(0).toUpperCase()+o.slice(1))),o.key].join("-")]=()=>(o.handler(),!0)}return i}});export{s as SendShortcutExtension};
2
2
  //# sourceMappingURL=SendShortcutExtension.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SendShortcutExtension.js","sources":["../../../../../src/editor/extensions/sendShortcut/SendShortcutExtension.ts"],"sourcesContent":["import { Extension } from '@tiptap/core';\nimport type { EditorSnapshot, KeyboardShortcut } from '../../BikEditor.types';\n\nexport const SendShortcutExtension = Extension.create({\n\tname: 'sendShortcut',\n\taddOptions() {\n\t\treturn {\n\t\t\tonSend: undefined as ((c: EditorSnapshot) => void) | undefined,\n\t\t\tsendShortcut: undefined as\n\t\t\t\t| { key: string; modifiers?: Array<'mod' | 'ctrl' | 'shift' | 'alt'> }\n\t\t\t\t| Array<{\n\t\t\t\t\t\tkey: string;\n\t\t\t\t\t\tmodifiers?: Array<'mod' | 'ctrl' | 'shift' | 'alt'>;\n\t\t\t\t }>\n\t\t\t\t| undefined,\n\t\t\textraShortcuts: [] as KeyboardShortcut[],\n\t\t};\n\t},\n\taddKeyboardShortcuts() {\n\t\tconst map: Record<string, () => boolean> = {};\n\n\t\t// onSend shortcut(s) — only registered when sendShortcut is explicitly configured\n\t\tif (this.options.onSend && this.options.sendShortcut) {\n\t\t\tconst shortcuts = Array.isArray(this.options.sendShortcut)\n\t\t\t\t? this.options.sendShortcut\n\t\t\t\t: [this.options.sendShortcut];\n\t\t\tconst handler = () => {\n\t\t\t\tthis.options.onSend!({\n\t\t\t\t\thtml: this.editor.getHTML(),\n\t\t\t\t\ttext: this.editor.getText(),\n\t\t\t\t\tisEmpty: this.editor.isEmpty,\n\t\t\t\t\tcharacterCount:\n\t\t\t\t\t\tthis.editor.storage.characterCount?.characters?.() ??\n\t\t\t\t\t\tthis.editor.getText().length,\n\t\t\t\t});\n\t\t\t\treturn true;\n\t\t\t};\n\t\t\tfor (const sc of shortcuts) {\n\t\t\t\tconst modParts = (sc.modifiers ?? []).map((m) =>\n\t\t\t\t\tm === 'mod' ? 'Mod' : m.charAt(0).toUpperCase() + m.slice(1),\n\t\t\t\t);\n\t\t\t\tconst combo = [...modParts, sc.key].join('-');\n\t\t\t\tmap[combo] = handler;\n\t\t\t}\n\t\t}\n\n\t\t// Consumer-defined shortcuts\n\t\tfor (const shortcut of this.options.extraShortcuts) {\n\t\t\tconst modParts = (shortcut.modifiers ?? []).map((m) =>\n\t\t\t\tm === 'mod' ? 'Mod' : m.charAt(0).toUpperCase() + m.slice(1),\n\t\t\t);\n\t\t\tconst combo = [...modParts, shortcut.key].join('-');\n\t\t\tmap[combo] = () => {\n\t\t\t\tshortcut.handler();\n\t\t\t\treturn true;\n\t\t\t};\n\t\t}\n\n\t\treturn map;\n\t},\n});\n"],"names":["SendShortcutExtension","Extension","create","name","addOptions","onSend","undefined","sendShortcut","extraShortcuts","addKeyboardShortcuts","map","this","options","shortcuts","Array","isArray","handler","html","editor","getHTML","text","getText","isEmpty","characterCount","_b","_a","storage","characters","call","length","sc","modifiers","m","charAt","toUpperCase","slice","key","join","shortcut"],"mappings":"mFAGaA,EAAwBC,EAAUC,OAAO,CACrDC,KAAM,eACNC,WAAUA,KACF,CACNC,YAAQC,EACRC,kBAAcD,EAOdE,eAAgB,KAGlBC,+BACC,MAAMC,EAAqC,CAAA,EAG3C,GAAIC,KAAKC,QAAQP,QAAUM,KAAKC,QAAQL,aAAc,CACrD,MAAMM,EAAYC,MAAMC,QAAQJ,KAAKC,QAAQL,cAC1CI,KAAKC,QAAQL,aACb,CAACI,KAAKC,QAAQL,cACXS,EAAUA,eASf,OARAL,KAAKC,QAAQP,OAAQ,CACpBY,KAAMN,KAAKO,OAAOC,UAClBC,KAAMT,KAAKO,OAAOG,UAClBC,QAASX,KAAKO,OAAOI,QACrBC,yBAC+C,QAA9CC,UAAAC,EAAAd,KAAKO,OAAOQ,QAAQH,qCAAgBI,kBAAU,IAAAH,OAAA,EAAAA,EAAAI,KAAAH,kBAC9Cd,KAAKO,OAAOG,UAAUQ,UAEjB,CAAI,EAEZ,IAAK,MAAMC,KAAMjB,EAAW,CAK3BH,EADc,aAHIe,EAAAK,EAAGC,yBAAa,IAAIrB,KAAKsB,GACpC,QAANA,EAAc,MAAQA,EAAEC,OAAO,GAAGC,cAAgBF,EAAEG,MAAM,KAE/BL,EAAGM,KAAKC,KAAK,MAC5BrB,CACb,CACD,CAGD,IAAK,MAAMsB,KAAY3B,KAAKC,QAAQJ,eAAgB,CAKnDE,EADc,aAHIc,EAAAc,EAASP,yBAAa,IAAIrB,KAAKsB,GAC1C,QAANA,EAAc,MAAQA,EAAEC,OAAO,GAAGC,cAAgBF,EAAEG,MAAM,KAE/BG,EAASF,KAAKC,KAAK,MAClC,KACZC,EAAStB,WACF,EAER,CAED,OAAON,CACR"}
1
+ {"version":3,"file":"SendShortcutExtension.js","sources":["../../../../../src/editor/extensions/sendShortcut/SendShortcutExtension.ts"],"sourcesContent":["import { Extension } from '@tiptap/core';\nimport type { EditorSnapshot, KeyboardShortcut } from '../../BikEditor.types';\nimport { extractContent } from '../../BikEditor.utils';\n\nexport const SendShortcutExtension = Extension.create({\n\tname: 'sendShortcut',\n\taddOptions() {\n\t\treturn {\n\t\t\tonSend: undefined as ((c: EditorSnapshot) => void) | undefined,\n\t\t\tsendShortcut: undefined as\n\t\t\t\t| { key: string; modifiers?: Array<'mod' | 'ctrl' | 'shift' | 'alt'> }\n\t\t\t\t| Array<{\n\t\t\t\t\t\tkey: string;\n\t\t\t\t\t\tmodifiers?: Array<'mod' | 'ctrl' | 'shift' | 'alt'>;\n\t\t\t\t }>\n\t\t\t\t| undefined,\n\t\t\textraShortcuts: [] as KeyboardShortcut[],\n\t\t};\n\t},\n\taddKeyboardShortcuts() {\n\t\tconst map: Record<string, () => boolean> = {};\n\n\t\t// onSend shortcut(s) — only registered when sendShortcut is explicitly configured\n\t\tif (this.options.onSend && this.options.sendShortcut) {\n\t\t\tconst shortcuts = Array.isArray(this.options.sendShortcut)\n\t\t\t\t? this.options.sendShortcut\n\t\t\t\t: [this.options.sendShortcut];\n\t\t\tconst handler = () => {\n\t\t\t\tthis.options.onSend!(extractContent(this.editor));\n\t\t\t\treturn true;\n\t\t\t};\n\t\t\tfor (const sc of shortcuts) {\n\t\t\t\tconst modParts = (sc.modifiers ?? []).map((m) =>\n\t\t\t\t\tm === 'mod' ? 'Mod' : m.charAt(0).toUpperCase() + m.slice(1),\n\t\t\t\t);\n\t\t\t\tconst combo = [...modParts, sc.key].join('-');\n\t\t\t\tmap[combo] = handler;\n\t\t\t}\n\t\t}\n\n\t\t// Consumer-defined shortcuts\n\t\tfor (const shortcut of this.options.extraShortcuts) {\n\t\t\tconst modParts = (shortcut.modifiers ?? []).map((m) =>\n\t\t\t\tm === 'mod' ? 'Mod' : m.charAt(0).toUpperCase() + m.slice(1),\n\t\t\t);\n\t\t\tconst combo = [...modParts, shortcut.key].join('-');\n\t\t\tmap[combo] = () => {\n\t\t\t\tshortcut.handler();\n\t\t\t\treturn true;\n\t\t\t};\n\t\t}\n\n\t\treturn map;\n\t},\n});\n"],"names":["SendShortcutExtension","Extension","create","name","addOptions","onSend","undefined","sendShortcut","extraShortcuts","addKeyboardShortcuts","map","this","options","shortcuts","Array","isArray","handler","extractContent","editor","sc","_a","modifiers","m","charAt","toUpperCase","slice","key","join","shortcut","_b"],"mappings":"6IAIaA,EAAwBC,EAAUC,OAAO,CACrDC,KAAM,eACNC,WAAUA,KACF,CACNC,YAAQC,EACRC,kBAAcD,EAOdE,eAAgB,KAGlBC,+BACC,MAAMC,EAAqC,CAAA,EAG3C,GAAIC,KAAKC,QAAQP,QAAUM,KAAKC,QAAQL,aAAc,CACrD,MAAMM,EAAYC,MAAMC,QAAQJ,KAAKC,QAAQL,cAC1CI,KAAKC,QAAQL,aACb,CAACI,KAAKC,QAAQL,cACXS,EAAUA,KACfL,KAAKC,QAAQP,OAAQY,EAAeN,KAAKO,UAClC,GAER,IAAK,MAAMC,KAAMN,EAAW,CAK3BH,EADc,aAHIU,EAAAD,EAAGE,yBAAa,IAAIX,KAAKY,GACpC,QAANA,EAAc,MAAQA,EAAEC,OAAO,GAAGC,cAAgBF,EAAEG,MAAM,KAE/BN,EAAGO,KAAKC,KAAK,MAC5BX,CACb,CACD,CAGD,IAAK,MAAMY,KAAYjB,KAAKC,QAAQJ,eAAgB,CAKnDE,EADc,aAHImB,EAAAD,EAASP,yBAAa,IAAIX,KAAKY,GAC1C,QAANA,EAAc,MAAQA,EAAEC,OAAO,GAAGC,cAAgBF,EAAEG,MAAM,KAE/BG,EAASF,KAAKC,KAAK,MAClC,KACZC,EAASZ,WACF,EAER,CAED,OAAON,CACR"}
@@ -1,2 +1,2 @@
1
- function e(e){if(!e)return"";if("undefined"!=typeof document){return r((new DOMParser).parseFromString(e,"text/html").body).replace(/\n{3,}/g,"\n\n").trim()}return function(e){return e.replace(/<strong[^>]*>([\s\S]*?)<\/strong>/gi,"*$1*").replace(/<b[^>]*>([\s\S]*?)<\/b>/gi,"*$1*").replace(/<em[^>]*>([\s\S]*?)<\/em>/gi,"$1").replace(/<i[^>]*>([\s\S]*?)<\/i>/gi,"$1").replace(/<s[^>]*>([\s\S]*?)<\/s>/gi,"$1").replace(/<del[^>]*>([\s\S]*?)<\/del>/gi,"$1").replace(/<a[^>]*>([\s\S]*?)<\/a>/gi,"$1").replace(/<br\s*\/?>/gi,"\n").replace(/<\/p>/gi,"\n").replace(/<\/div>/gi,"\n").replace(/<\/h[1-6]>/gi,"\n").replace(/<li[^>]*>/gi,"• ").replace(/<\/li>/gi,"\n").replace(/<[^>]+>/g,"").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&nbsp;/g," ").replace(/\n{3,}/g,"\n\n").trim()}(e)}function r(e){var a;if(e.nodeType===Node.TEXT_NODE)return null!==(a=e.textContent)&&void 0!==a?a:"";if(e.nodeType!==Node.ELEMENT_NODE)return"";const n=e,c=n.tagName.toLowerCase(),s=function(e){return Array.from(e.childNodes).map(r).join("")}(n);switch(c){case"strong":case"b":return s?`*${s}*`:"";case"em":case"i":case"s":case"del":case"strike":case"code":case"pre":case"a":case"ul":case"ol":case"body":default:return s;case"br":return"\n";case"p":case"div":return s?`${s}\n`:"\n";case"h1":case"h2":case"h3":case"h4":case"h5":case"h6":return s?`*${s}*\n`:"\n";case"li":return`• ${s.trimEnd()}\n`;case"blockquote":return s+"\n"}}export{e as toLiveChatText};
1
+ function e(e){if(!e)return"";if("undefined"!=typeof document){return r((new DOMParser).parseFromString(e,"text/html").body).trim()}return function(e){return e.replace(/<strong[^>]*>([\s\S]*?)<\/strong>/gi,"*$1*").replace(/<b[^>]*>([\s\S]*?)<\/b>/gi,"*$1*").replace(/<em[^>]*>([\s\S]*?)<\/em>/gi,"$1").replace(/<i[^>]*>([\s\S]*?)<\/i>/gi,"$1").replace(/<s[^>]*>([\s\S]*?)<\/s>/gi,"$1").replace(/<del[^>]*>([\s\S]*?)<\/del>/gi,"$1").replace(/<a[^>]*>([\s\S]*?)<\/a>/gi,"$1").replace(/<p[^>]*>\s*<br\s*\/?>\s*<\/p>/gi,"\n").replace(/<br\s*\/?>/gi,"\n").replace(/<\/p>/gi,"\n").replace(/<\/div>/gi,"\n").replace(/<\/h[1-6]>/gi,"\n").replace(/<li[^>]*>/gi,"• ").replace(/<\/li>/gi,"\n").replace(/<[^>]+>/g,"").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&nbsp;/g," ").trim()}(e)}function r(e){var a,n,c;if(e.nodeType===Node.TEXT_NODE)return null!==(a=e.textContent)&&void 0!==a?a:"";if(e.nodeType!==Node.ELEMENT_NODE)return"";const s=e,t=s.tagName.toLowerCase(),i=function(e){return Array.from(e.childNodes).map(r).join("")}(s);switch(t){case"strong":case"b":return i?`*${i}*`:"";case"em":case"i":case"s":case"del":case"strike":case"code":case"pre":case"a":case"ul":case"ol":case"body":default:return i;case"br":return"\n";case"p":case"div":return 1===s.childNodes.length&&"br"===(null===(c=null===(n=s.firstChild)||void 0===n?void 0:n.tagName)||void 0===c?void 0:c.toLowerCase())?"\n":i?`${i}\n`:"\n";case"h1":case"h2":case"h3":case"h4":case"h5":case"h6":return i?`*${i}*\n`:"\n";case"li":return`• ${i.trimEnd()}\n`;case"blockquote":return i+"\n"}}export{e as toLiveChatText};
2
2
  //# sourceMappingURL=toLiveChatText.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"toLiveChatText.js","sources":["../../../../src/editor/serializers/toLiveChatText.ts"],"sourcesContent":["/**\n * Converts TipTap HTML to LiveChat plain text.\n *\n * LiveChat supports **bold** (`*text*`) but NOT italic or strikethrough.\n * Italic and strikethrough marks are stripped — the inner text is preserved.\n * Links emit only the display text (href is dropped).\n *\n * @example\n * const { html } = ref.current?.getContent();\n * const lcText = toLiveChatText(html);\n * sendLiveChat({ text: lcText });\n */\nexport function toLiveChatText(html: string): string {\n\tif (!html) return '';\n\n\tif (typeof document !== 'undefined') {\n\t\tconst doc = new DOMParser().parseFromString(html, 'text/html');\n\t\treturn serializeNode(doc.body)\n\t\t\t.replace(/\\n{3,}/g, '\\n\\n')\n\t\t\t.trim();\n\t}\n\n\treturn ssrFallback(html);\n}\n\n// ---------------------------------------------------------------------------\n// Browser path — DOM-based, handles nested marks correctly\n// ---------------------------------------------------------------------------\n\nfunction serializeNode(node: Node): string {\n\tif (node.nodeType === Node.TEXT_NODE) return node.textContent ?? '';\n\tif (node.nodeType !== Node.ELEMENT_NODE) return '';\n\n\tconst el = node as Element;\n\tconst tag = el.tagName.toLowerCase();\n\tconst inner = serializeChildren(el);\n\n\tswitch (tag) {\n\t\tcase 'strong':\n\t\tcase 'b':\n\t\t\treturn inner ? `*${inner}*` : '';\n\n\t\t// Italic and strike: strip marks, keep inner text\n\t\tcase 'em':\n\t\tcase 'i':\n\t\tcase 's':\n\t\tcase 'del':\n\t\tcase 'strike':\n\t\t\treturn inner;\n\n\t\tcase 'code':\n\t\tcase 'pre':\n\t\t\treturn inner;\n\n\t\tcase 'a':\n\t\t\t// LiveChat does not support hyperlinks — emit display text only\n\t\t\treturn inner;\n\n\t\tcase 'br':\n\t\t\treturn '\\n';\n\n\t\tcase 'p':\n\t\tcase 'div':\n\t\t\treturn inner ? `${inner}\\n` : '\\n';\n\n\t\tcase 'h1':\n\t\tcase 'h2':\n\t\tcase 'h3':\n\t\tcase 'h4':\n\t\tcase 'h5':\n\t\tcase 'h6':\n\t\t\treturn inner ? `*${inner}*\\n` : '\\n';\n\n\t\tcase 'ul':\n\t\tcase 'ol':\n\t\t\treturn inner;\n\n\t\tcase 'li':\n\t\t\treturn `• ${inner.trimEnd()}\\n`;\n\n\t\tcase 'blockquote':\n\t\t\treturn inner + '\\n';\n\n\t\tcase 'body':\n\t\tdefault:\n\t\t\treturn inner;\n\t}\n}\n\nfunction serializeChildren(el: Element): string {\n\treturn Array.from(el.childNodes).map(serializeNode).join('');\n}\n\n// ---------------------------------------------------------------------------\n// SSR / Node.js fallback — regex-based, best-effort for simple markup\n// ---------------------------------------------------------------------------\n\nfunction ssrFallback(html: string): string {\n\treturn html\n\t\t.replace(/<strong[^>]*>([\\s\\S]*?)<\\/strong>/gi, '*$1*')\n\t\t.replace(/<b[^>]*>([\\s\\S]*?)<\\/b>/gi, '*$1*')\n\t\t.replace(/<em[^>]*>([\\s\\S]*?)<\\/em>/gi, '$1')\n\t\t.replace(/<i[^>]*>([\\s\\S]*?)<\\/i>/gi, '$1')\n\t\t.replace(/<s[^>]*>([\\s\\S]*?)<\\/s>/gi, '$1')\n\t\t.replace(/<del[^>]*>([\\s\\S]*?)<\\/del>/gi, '$1')\n\t\t.replace(/<a[^>]*>([\\s\\S]*?)<\\/a>/gi, '$1')\n\t\t.replace(/<br\\s*\\/?>/gi, '\\n')\n\t\t.replace(/<\\/p>/gi, '\\n')\n\t\t.replace(/<\\/div>/gi, '\\n')\n\t\t.replace(/<\\/h[1-6]>/gi, '\\n')\n\t\t.replace(/<li[^>]*>/gi, '• ')\n\t\t.replace(/<\\/li>/gi, '\\n')\n\t\t.replace(/<[^>]+>/g, '')\n\t\t.replace(/&amp;/g, '&')\n\t\t.replace(/&lt;/g, '<')\n\t\t.replace(/&gt;/g, '>')\n\t\t.replace(/&nbsp;/g, ' ')\n\t\t.replace(/\\n{3,}/g, '\\n\\n')\n\t\t.trim();\n}\n"],"names":["toLiveChatText","html","document","serializeNode","DOMParser","parseFromString","body","replace","trim","ssrFallback","node","nodeType","Node","TEXT_NODE","textContent","_a","ELEMENT_NODE","el","tag","tagName","toLowerCase","inner","Array","from","childNodes","map","join","serializeChildren","trimEnd"],"mappings":"AAYM,SAAUA,EAAeC,GAC9B,IAAKA,EAAM,MAAO,GAElB,GAAwB,oBAAbC,SAA0B,CAEpC,OAAOC,GADK,IAAIC,WAAYC,gBAAgBJ,EAAM,aACzBK,MACvBC,QAAQ,UAAW,QACnBC,MACF,CAED,OA2ED,SAAqBP,GACpB,OAAOA,EACLM,QAAQ,sCAAuC,QAC/CA,QAAQ,4BAA6B,QACrCA,QAAQ,8BAA+B,MACvCA,QAAQ,4BAA6B,MACrCA,QAAQ,4BAA6B,MACrCA,QAAQ,gCAAiC,MACzCA,QAAQ,4BAA6B,MACrCA,QAAQ,eAAgB,MACxBA,QAAQ,UAAW,MACnBA,QAAQ,YAAa,MACrBA,QAAQ,eAAgB,MACxBA,QAAQ,cAAe,MACvBA,QAAQ,WAAY,MACpBA,QAAQ,WAAY,IACpBA,QAAQ,SAAU,KAClBA,QAAQ,QAAS,KACjBA,QAAQ,QAAS,KACjBA,QAAQ,UAAW,KACnBA,QAAQ,UAAW,QACnBC,MACH,CAjGQC,CAAYR,EACpB,CAMA,SAASE,EAAcO,SACtB,GAAIA,EAAKC,WAAaC,KAAKC,UAAW,OAAuB,UAAhBH,EAAKI,mBAAW,IAAAC,EAAAA,EAAI,GACjE,GAAIL,EAAKC,WAAaC,KAAKI,aAAc,MAAO,GAEhD,MAAMC,EAAKP,EACLQ,EAAMD,EAAGE,QAAQC,cACjBC,EAsDP,SAA2BJ,GAC1B,OAAOK,MAAMC,KAAKN,EAAGO,YAAYC,IAAItB,GAAeuB,KAAK,GAC1D,CAxDeC,CAAkBV,GAEhC,OAAQC,GACP,IAAK,SACL,IAAK,IACJ,OAAOG,EAAQ,IAAIA,KAAW,GAG/B,IAAK,KACL,IAAK,IACL,IAAK,IACL,IAAK,MACL,IAAK,SAGL,IAAK,OACL,IAAK,MAGL,IAAK,IAmBL,IAAK,KACL,IAAK,KASL,IAAK,OACL,QACC,OAAOA,EA3BR,IAAK,KACJ,MAAO,KAER,IAAK,IACL,IAAK,MACJ,OAAOA,EAAQ,GAAGA,MAAY,KAE/B,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACJ,OAAOA,EAAQ,IAAIA,OAAa,KAMjC,IAAK,KACJ,WAAYA,EAAMO,cAEnB,IAAK,aACJ,OAAOP,EAAQ,KAMlB"}
1
+ {"version":3,"file":"toLiveChatText.js","sources":["../../../../src/editor/serializers/toLiveChatText.ts"],"sourcesContent":["/**\n * Converts TipTap HTML to LiveChat plain text.\n *\n * LiveChat supports **bold** (`*text*`) but NOT italic or strikethrough.\n * Italic and strikethrough marks are stripped — the inner text is preserved.\n * Links emit only the display text (href is dropped).\n *\n * @example\n * const { html } = ref.current?.getContent();\n * const lcText = toLiveChatText(html);\n * sendLiveChat({ text: lcText });\n */\nexport function toLiveChatText(html: string): string {\n\tif (!html) return '';\n\n\tif (typeof document !== 'undefined') {\n\t\tconst doc = new DOMParser().parseFromString(html, 'text/html');\n\t\treturn serializeNode(doc.body).trim();\n\t}\n\n\treturn ssrFallback(html);\n}\n\n// ---------------------------------------------------------------------------\n// Browser path — DOM-based, handles nested marks correctly\n// ---------------------------------------------------------------------------\n\nfunction serializeNode(node: Node): string {\n\tif (node.nodeType === Node.TEXT_NODE) return node.textContent ?? '';\n\tif (node.nodeType !== Node.ELEMENT_NODE) return '';\n\n\tconst el = node as Element;\n\tconst tag = el.tagName.toLowerCase();\n\tconst inner = serializeChildren(el);\n\n\tswitch (tag) {\n\t\tcase 'strong':\n\t\tcase 'b':\n\t\t\treturn inner ? `*${inner}*` : '';\n\n\t\t// Italic and strike: strip marks, keep inner text\n\t\tcase 'em':\n\t\tcase 'i':\n\t\tcase 's':\n\t\tcase 'del':\n\t\tcase 'strike':\n\t\t\treturn inner;\n\n\t\tcase 'code':\n\t\tcase 'pre':\n\t\t\treturn inner;\n\n\t\tcase 'a':\n\t\t\t// LiveChat does not support hyperlinks — emit display text only\n\t\t\treturn inner;\n\n\t\tcase 'br':\n\t\t\treturn '\\n';\n\n\t\tcase 'p':\n\t\tcase 'div': {\n\t\t\tconst isBlankLine =\n\t\t\t\tel.childNodes.length === 1 &&\n\t\t\t\t(el.firstChild as Element)?.tagName?.toLowerCase() === 'br';\n\t\t\treturn isBlankLine ? '\\n' : inner ? `${inner}\\n` : '\\n';\n\t\t}\n\n\t\tcase 'h1':\n\t\tcase 'h2':\n\t\tcase 'h3':\n\t\tcase 'h4':\n\t\tcase 'h5':\n\t\tcase 'h6':\n\t\t\treturn inner ? `*${inner}*\\n` : '\\n';\n\n\t\tcase 'ul':\n\t\tcase 'ol':\n\t\t\treturn inner;\n\n\t\tcase 'li':\n\t\t\treturn `• ${inner.trimEnd()}\\n`;\n\n\t\tcase 'blockquote':\n\t\t\treturn inner + '\\n';\n\n\t\tcase 'body':\n\t\tdefault:\n\t\t\treturn inner;\n\t}\n}\n\nfunction serializeChildren(el: Element): string {\n\treturn Array.from(el.childNodes).map(serializeNode).join('');\n}\n\n// ---------------------------------------------------------------------------\n// SSR / Node.js fallback — regex-based, best-effort for simple markup\n// ---------------------------------------------------------------------------\n\nfunction ssrFallback(html: string): string {\n\treturn html\n\t\t.replace(/<strong[^>]*>([\\s\\S]*?)<\\/strong>/gi, '*$1*')\n\t\t.replace(/<b[^>]*>([\\s\\S]*?)<\\/b>/gi, '*$1*')\n\t\t.replace(/<em[^>]*>([\\s\\S]*?)<\\/em>/gi, '$1')\n\t\t.replace(/<i[^>]*>([\\s\\S]*?)<\\/i>/gi, '$1')\n\t\t.replace(/<s[^>]*>([\\s\\S]*?)<\\/s>/gi, '$1')\n\t\t.replace(/<del[^>]*>([\\s\\S]*?)<\\/del>/gi, '$1')\n\t\t.replace(/<a[^>]*>([\\s\\S]*?)<\\/a>/gi, '$1')\n\t\t.replace(/<p[^>]*>\\s*<br\\s*\\/?>\\s*<\\/p>/gi, '\\n')\n\t\t.replace(/<br\\s*\\/?>/gi, '\\n')\n\t\t.replace(/<\\/p>/gi, '\\n')\n\t\t.replace(/<\\/div>/gi, '\\n')\n\t\t.replace(/<\\/h[1-6]>/gi, '\\n')\n\t\t.replace(/<li[^>]*>/gi, '• ')\n\t\t.replace(/<\\/li>/gi, '\\n')\n\t\t.replace(/<[^>]+>/g, '')\n\t\t.replace(/&amp;/g, '&')\n\t\t.replace(/&lt;/g, '<')\n\t\t.replace(/&gt;/g, '>')\n\t\t.replace(/&nbsp;/g, ' ')\n\t\t.trim();\n}\n"],"names":["toLiveChatText","html","document","serializeNode","DOMParser","parseFromString","body","trim","replace","ssrFallback","node","nodeType","Node","TEXT_NODE","textContent","_a","ELEMENT_NODE","el","tag","tagName","toLowerCase","inner","Array","from","childNodes","map","join","serializeChildren","length","_c","_b","firstChild","trimEnd"],"mappings":"AAYM,SAAUA,EAAeC,GAC9B,IAAKA,EAAM,MAAO,GAElB,GAAwB,oBAAbC,SAA0B,CAEpC,OAAOC,GADK,IAAIC,WAAYC,gBAAgBJ,EAAM,aACzBK,MAAMC,MAC/B,CAED,OA+ED,SAAqBN,GACpB,OAAOA,EACLO,QAAQ,sCAAuC,QAC/CA,QAAQ,4BAA6B,QACrCA,QAAQ,8BAA+B,MACvCA,QAAQ,4BAA6B,MACrCA,QAAQ,4BAA6B,MACrCA,QAAQ,gCAAiC,MACzCA,QAAQ,4BAA6B,MACrCA,QAAQ,kCAAmC,MAC3CA,QAAQ,eAAgB,MACxBA,QAAQ,UAAW,MACnBA,QAAQ,YAAa,MACrBA,QAAQ,eAAgB,MACxBA,QAAQ,cAAe,MACvBA,QAAQ,WAAY,MACpBA,QAAQ,WAAY,IACpBA,QAAQ,SAAU,KAClBA,QAAQ,QAAS,KACjBA,QAAQ,QAAS,KACjBA,QAAQ,UAAW,KACnBD,MACH,CArGQE,CAAYR,EACpB,CAMA,SAASE,EAAcO,aACtB,GAAIA,EAAKC,WAAaC,KAAKC,UAAW,OAAuB,UAAhBH,EAAKI,mBAAW,IAAAC,EAAAA,EAAI,GACjE,GAAIL,EAAKC,WAAaC,KAAKI,aAAc,MAAO,GAEhD,MAAMC,EAAKP,EACLQ,EAAMD,EAAGE,QAAQC,cACjBC,EA0DP,SAA2BJ,GAC1B,OAAOK,MAAMC,KAAKN,EAAGO,YAAYC,IAAItB,GAAeuB,KAAK,GAC1D,CA5DeC,CAAkBV,GAEhC,OAAQC,GACP,IAAK,SACL,IAAK,IACJ,OAAOG,EAAQ,IAAIA,KAAW,GAG/B,IAAK,KACL,IAAK,IACL,IAAK,IACL,IAAK,MACL,IAAK,SAGL,IAAK,OACL,IAAK,MAGL,IAAK,IAuBL,IAAK,KACL,IAAK,KASL,IAAK,OACL,QACC,OAAOA,EA/BR,IAAK,KACJ,MAAO,KAER,IAAK,IACL,IAAK,MAIJ,OAF0B,IAAzBJ,EAAGO,WAAWI,QACyC,QAApB,QAAnCC,EAA0B,QAA1BC,EAACb,EAAGc,kBAAsB,IAAAD,OAAA,EAAAA,EAAEX,eAAO,IAAAU,OAAA,EAAAA,EAAET,eACjB,KAAOC,KAAWA,MAAY,KAGpD,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACJ,OAAOA,EAAQ,IAAIA,OAAa,KAMjC,IAAK,KACJ,WAAYA,EAAMW,cAEnB,IAAK,aACJ,OAAOX,EAAQ,KAMlB"}
@@ -1,2 +1,2 @@
1
- function e(e){if(!e)return"";if("undefined"!=typeof document){return r((new DOMParser).parseFromString(e,"text/html").body).replace(/\n{3,}/g,"\n\n").trim()}return function(e){return e.replace(/<strong[^>]*>([\s\S]*?)<\/strong>/gi,"*$1*").replace(/<b[^>]*>([\s\S]*?)<\/b>/gi,"*$1*").replace(/<em[^>]*>([\s\S]*?)<\/em>/gi,"_$1_").replace(/<i[^>]*>([\s\S]*?)<\/i>/gi,"_$1_").replace(/<s[^>]*>([\s\S]*?)<\/s>/gi,"~$1~").replace(/<del[^>]*>([\s\S]*?)<\/del>/gi,"~$1~").replace(/<code[^>]*>([\s\S]*?)<\/code>/gi,"`$1`").replace(/<a[^>]*>([\s\S]*?)<\/a>/gi,"$1").replace(/<br\s*\/?>/gi,"\n").replace(/<\/p>/gi,"\n").replace(/<\/div>/gi,"\n").replace(/<\/h[1-6]>/gi,"\n").replace(/<li[^>]*>/gi,"• ").replace(/<\/li>/gi,"\n").replace(/<[^>]+>/g,"").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&nbsp;/g," ").replace(/\n{3,}/g,"\n\n").trim()}(e)}function r(e){var n;if(e.nodeType===Node.TEXT_NODE)return null!==(n=e.textContent)&&void 0!==n?n:"";if(e.nodeType!==Node.ELEMENT_NODE)return"";const a=e,c=a.tagName.toLowerCase(),t=function(e){return Array.from(e.childNodes).map(r).join("")}(a);switch(c){case"strong":case"b":return t?`*${t}*`:"";case"em":case"i":return t?`_${t}_`:"";case"s":case"del":case"strike":return t?`~${t}~`:"";case"code":return t?`\`${t}\``:"";case"pre":return t?`\`\`\`${t}\`\`\``:"";case"a":case"ul":case"ol":case"body":default:return t;case"br":return"\n";case"p":case"div":return t?`${t}\n`:"\n";case"h1":case"h2":case"h3":case"h4":case"h5":case"h6":return t?`*${t}*\n`:"\n";case"li":return`• ${t.trimEnd()}\n`;case"blockquote":return t.split("\n").map((e=>e?`> ${e}`:"")).join("\n")+"\n"}}export{e as toWhatsAppText};
1
+ function e(e){if(!e)return"";if("undefined"!=typeof document){return r((new DOMParser).parseFromString(e,"text/html").body).trim()}return function(e){return e.replace(/<strong[^>]*>([\s\S]*?)<\/strong>/gi,"*$1*").replace(/<b[^>]*>([\s\S]*?)<\/b>/gi,"*$1*").replace(/<em[^>]*>([\s\S]*?)<\/em>/gi,"_$1_").replace(/<i[^>]*>([\s\S]*?)<\/i>/gi,"_$1_").replace(/<s[^>]*>([\s\S]*?)<\/s>/gi,"~$1~").replace(/<del[^>]*>([\s\S]*?)<\/del>/gi,"~$1~").replace(/<code[^>]*>([\s\S]*?)<\/code>/gi,"`$1`").replace(/<a[^>]*>([\s\S]*?)<\/a>/gi,"$1").replace(/<p[^>]*>\s*<br\s*\/?>\s*<\/p>/gi,"\n").replace(/<br\s*\/?>/gi,"\n").replace(/<\/p>/gi,"\n").replace(/<\/div>/gi,"\n").replace(/<\/h[1-6]>/gi,"\n").replace(/<li[^>]*>/gi,"• ").replace(/<\/li>/gi,"\n").replace(/<[^>]+>/g,"").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&nbsp;/g," ").trim()}(e)}function r(e){var n,a,c;if(e.nodeType===Node.TEXT_NODE)return null!==(n=e.textContent)&&void 0!==n?n:"";if(e.nodeType!==Node.ELEMENT_NODE)return"";const s=e,t=s.tagName.toLowerCase(),i=function(e){return Array.from(e.childNodes).map(r).join("")}(s);switch(t){case"strong":case"b":return i?`*${i}*`:"";case"em":case"i":return i?`_${i}_`:"";case"s":case"del":case"strike":return i?`~${i}~`:"";case"code":return i?`\`${i}\``:"";case"pre":return i?`\`\`\`${i}\`\`\``:"";case"a":case"ul":case"ol":case"body":default:return i;case"br":return"\n";case"p":case"div":return 1===s.childNodes.length&&"br"===(null===(c=null===(a=s.firstChild)||void 0===a?void 0:a.tagName)||void 0===c?void 0:c.toLowerCase())?"\n":i?`${i}\n`:"\n";case"h1":case"h2":case"h3":case"h4":case"h5":case"h6":return i?`*${i}*\n`:"\n";case"li":return`• ${i.trimEnd()}\n`;case"blockquote":return i.split("\n").map((e=>e?`> ${e}`:"")).join("\n")+"\n"}}export{e as toWhatsAppText};
2
2
  //# sourceMappingURL=toWhatsAppText.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"toWhatsAppText.js","sources":["../../../../src/editor/serializers/toWhatsAppText.ts"],"sourcesContent":["/**\n * Converts TipTap HTML to WhatsApp-flavoured markdown text.\n *\n * WhatsApp formatting:\n * *bold* _italic_ ~strikethrough~ ```monospace```\n *\n * Links: WhatsApp does not support hyperlinks.\n * <a href=\"https://…\">Visit us</a> → Visit us (display text kept, href dropped)\n *\n * @example\n * const { html } = ref.current?.getContent();\n * const waText = toWhatsAppText(html);\n * sendWhatsApp({ text: waText });\n */\nexport function toWhatsAppText(html: string): string {\n\tif (!html) return '';\n\n\tif (typeof document !== 'undefined') {\n\t\tconst doc = new DOMParser().parseFromString(html, 'text/html');\n\t\treturn serializeNode(doc.body)\n\t\t\t.replace(/\\n{3,}/g, '\\n\\n')\n\t\t\t.trim();\n\t}\n\n\t// SSR / Node.js fallback — handles simple non-nested markup\n\treturn ssrFallback(html);\n}\n\n// ---------------------------------------------------------------------------\n// Browser path — DOM-based, handles nested marks correctly\n// ---------------------------------------------------------------------------\n\nfunction serializeNode(node: Node): string {\n\tif (node.nodeType === Node.TEXT_NODE) {\n\t\treturn node.textContent ?? '';\n\t}\n\tif (node.nodeType !== Node.ELEMENT_NODE) return '';\n\n\tconst el = node as Element;\n\tconst tag = el.tagName.toLowerCase();\n\tconst inner = serializeChildren(el);\n\n\tswitch (tag) {\n\t\tcase 'strong':\n\t\tcase 'b':\n\t\t\treturn inner ? `*${inner}*` : '';\n\n\t\tcase 'em':\n\t\tcase 'i':\n\t\t\treturn inner ? `_${inner}_` : '';\n\n\t\tcase 's':\n\t\tcase 'del':\n\t\tcase 'strike':\n\t\t\treturn inner ? `~${inner}~` : '';\n\n\t\tcase 'code':\n\t\t\treturn inner ? `\\`${inner}\\`` : '';\n\n\t\tcase 'pre':\n\t\t\treturn inner ? `\\`\\`\\`${inner}\\`\\`\\`` : '';\n\n\t\tcase 'a':\n\t\t\treturn inner;\n\n\t\tcase 'br':\n\t\t\treturn '\\n';\n\n\t\tcase 'p':\n\t\tcase 'div':\n\t\t\treturn inner ? `${inner}\\n` : '\\n';\n\n\t\tcase 'h1':\n\t\tcase 'h2':\n\t\tcase 'h3':\n\t\tcase 'h4':\n\t\tcase 'h5':\n\t\tcase 'h6':\n\t\t\treturn inner ? `*${inner}*\\n` : '\\n';\n\n\t\tcase 'ul':\n\t\tcase 'ol':\n\t\t\treturn inner;\n\n\t\tcase 'li':\n\t\t\treturn `• ${inner.trimEnd()}\\n`;\n\n\t\tcase 'blockquote':\n\t\t\treturn (\n\t\t\t\tinner\n\t\t\t\t\t.split('\\n')\n\t\t\t\t\t.map((l) => (l ? `> ${l}` : ''))\n\t\t\t\t\t.join('\\n') + '\\n'\n\t\t\t);\n\n\t\tcase 'body':\n\t\tdefault:\n\t\t\treturn inner;\n\t}\n}\n\nfunction serializeChildren(el: Element): string {\n\treturn Array.from(el.childNodes).map(serializeNode).join('');\n}\n\n// ---------------------------------------------------------------------------\n// SSR fallback — regex-based, best-effort for simple markup\n// ---------------------------------------------------------------------------\n\nfunction ssrFallback(html: string): string {\n\treturn html\n\t\t.replace(/<strong[^>]*>([\\s\\S]*?)<\\/strong>/gi, '*$1*')\n\t\t.replace(/<b[^>]*>([\\s\\S]*?)<\\/b>/gi, '*$1*')\n\t\t.replace(/<em[^>]*>([\\s\\S]*?)<\\/em>/gi, '_$1_')\n\t\t.replace(/<i[^>]*>([\\s\\S]*?)<\\/i>/gi, '_$1_')\n\t\t.replace(/<s[^>]*>([\\s\\S]*?)<\\/s>/gi, '~$1~')\n\t\t.replace(/<del[^>]*>([\\s\\S]*?)<\\/del>/gi, '~$1~')\n\t\t.replace(/<code[^>]*>([\\s\\S]*?)<\\/code>/gi, '`$1`')\n\t\t.replace(/<a[^>]*>([\\s\\S]*?)<\\/a>/gi, '$1')\n\t\t.replace(/<br\\s*\\/?>/gi, '\\n')\n\t\t.replace(/<\\/p>/gi, '\\n')\n\t\t.replace(/<\\/div>/gi, '\\n')\n\t\t.replace(/<\\/h[1-6]>/gi, '\\n')\n\t\t.replace(/<li[^>]*>/gi, '• ')\n\t\t.replace(/<\\/li>/gi, '\\n')\n\t\t.replace(/<[^>]+>/g, '')\n\t\t.replace(/&amp;/g, '&')\n\t\t.replace(/&lt;/g, '<')\n\t\t.replace(/&gt;/g, '>')\n\t\t.replace(/&nbsp;/g, ' ')\n\t\t.replace(/\\n{3,}/g, '\\n\\n')\n\t\t.trim();\n}\n"],"names":["toWhatsAppText","html","document","serializeNode","DOMParser","parseFromString","body","replace","trim","ssrFallback","node","nodeType","Node","TEXT_NODE","textContent","_a","ELEMENT_NODE","el","tag","tagName","toLowerCase","inner","Array","from","childNodes","map","join","serializeChildren","trimEnd","split","l"],"mappings":"AAcM,SAAUA,EAAeC,GAC9B,IAAKA,EAAM,MAAO,GAElB,GAAwB,oBAAbC,SAA0B,CAEpC,OAAOC,GADK,IAAIC,WAAYC,gBAAgBJ,EAAM,aACzBK,MACvBC,QAAQ,UAAW,QACnBC,MACF,CAGD,OAoFD,SAAqBP,GACpB,OAAOA,EACLM,QAAQ,sCAAuC,QAC/CA,QAAQ,4BAA6B,QACrCA,QAAQ,8BAA+B,QACvCA,QAAQ,4BAA6B,QACrCA,QAAQ,4BAA6B,QACrCA,QAAQ,gCAAiC,QACzCA,QAAQ,kCAAmC,QAC3CA,QAAQ,4BAA6B,MACrCA,QAAQ,eAAgB,MACxBA,QAAQ,UAAW,MACnBA,QAAQ,YAAa,MACrBA,QAAQ,eAAgB,MACxBA,QAAQ,cAAe,MACvBA,QAAQ,WAAY,MACpBA,QAAQ,WAAY,IACpBA,QAAQ,SAAU,KAClBA,QAAQ,QAAS,KACjBA,QAAQ,QAAS,KACjBA,QAAQ,UAAW,KACnBA,QAAQ,UAAW,QACnBC,MACH,CA3GQC,CAAYR,EACpB,CAMA,SAASE,EAAcO,SACtB,GAAIA,EAAKC,WAAaC,KAAKC,UAC1B,OAAuB,UAAhBH,EAAKI,mBAAW,IAAAC,EAAAA,EAAI,GAE5B,GAAIL,EAAKC,WAAaC,KAAKI,aAAc,MAAO,GAEhD,MAAMC,EAAKP,EACLQ,EAAMD,EAAGE,QAAQC,cACjBC,EA6DP,SAA2BJ,GAC1B,OAAOK,MAAMC,KAAKN,EAAGO,YAAYC,IAAItB,GAAeuB,KAAK,GAC1D,CA/DeC,CAAkBV,GAEhC,OAAQC,GACP,IAAK,SACL,IAAK,IACJ,OAAOG,EAAQ,IAAIA,KAAW,GAE/B,IAAK,KACL,IAAK,IACJ,OAAOA,EAAQ,IAAIA,KAAW,GAE/B,IAAK,IACL,IAAK,MACL,IAAK,SACJ,OAAOA,EAAQ,IAAIA,KAAW,GAE/B,IAAK,OACJ,OAAOA,EAAQ,KAAKA,MAAY,GAEjC,IAAK,MACJ,OAAOA,EAAQ,SAASA,UAAgB,GAEzC,IAAK,IAkBL,IAAK,KACL,IAAK,KAcL,IAAK,OACL,QACC,OAAOA,EAhCR,IAAK,KACJ,MAAO,KAER,IAAK,IACL,IAAK,MACJ,OAAOA,EAAQ,GAAGA,MAAY,KAE/B,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACJ,OAAOA,EAAQ,IAAIA,OAAa,KAMjC,IAAK,KACJ,WAAYA,EAAMO,cAEnB,IAAK,aACJ,OACCP,EACEQ,MAAM,MACNJ,KAAKK,GAAOA,EAAI,KAAKA,IAAM,KAC3BJ,KAAK,MAAQ,KAOnB"}
1
+ {"version":3,"file":"toWhatsAppText.js","sources":["../../../../src/editor/serializers/toWhatsAppText.ts"],"sourcesContent":["/**\n * Converts TipTap HTML to WhatsApp-flavoured markdown text.\n *\n * WhatsApp formatting:\n * *bold* _italic_ ~strikethrough~ ```monospace```\n *\n * Links: WhatsApp does not support hyperlinks.\n * <a href=\"https://…\">Visit us</a> → Visit us (display text kept, href dropped)\n *\n * @example\n * const { html } = ref.current?.getContent();\n * const waText = toWhatsAppText(html);\n * sendWhatsApp({ text: waText });\n */\nexport function toWhatsAppText(html: string): string {\n\tif (!html) return '';\n\n\tif (typeof document !== 'undefined') {\n\t\tconst doc = new DOMParser().parseFromString(html, 'text/html');\n\t\treturn serializeNode(doc.body).trim();\n\t}\n\n\t// SSR / Node.js fallback — handles simple non-nested markup\n\treturn ssrFallback(html);\n}\n\n// ---------------------------------------------------------------------------\n// Browser path — DOM-based, handles nested marks correctly\n// ---------------------------------------------------------------------------\n\nfunction serializeNode(node: Node): string {\n\tif (node.nodeType === Node.TEXT_NODE) {\n\t\treturn node.textContent ?? '';\n\t}\n\tif (node.nodeType !== Node.ELEMENT_NODE) return '';\n\n\tconst el = node as Element;\n\tconst tag = el.tagName.toLowerCase();\n\tconst inner = serializeChildren(el);\n\n\tswitch (tag) {\n\t\tcase 'strong':\n\t\tcase 'b':\n\t\t\treturn inner ? `*${inner}*` : '';\n\n\t\tcase 'em':\n\t\tcase 'i':\n\t\t\treturn inner ? `_${inner}_` : '';\n\n\t\tcase 's':\n\t\tcase 'del':\n\t\tcase 'strike':\n\t\t\treturn inner ? `~${inner}~` : '';\n\n\t\tcase 'code':\n\t\t\treturn inner ? `\\`${inner}\\`` : '';\n\n\t\tcase 'pre':\n\t\t\treturn inner ? `\\`\\`\\`${inner}\\`\\`\\`` : '';\n\n\t\tcase 'a':\n\t\t\treturn inner;\n\n\t\tcase 'br':\n\t\t\treturn '\\n';\n\n\t\tcase 'p':\n\t\tcase 'div': {\n\t\t\tconst isBlankLine =\n\t\t\t\tel.childNodes.length === 1 &&\n\t\t\t\t(el.firstChild as Element)?.tagName?.toLowerCase() === 'br';\n\t\t\treturn isBlankLine ? '\\n' : inner ? `${inner}\\n` : '\\n';\n\t\t}\n\n\t\tcase 'h1':\n\t\tcase 'h2':\n\t\tcase 'h3':\n\t\tcase 'h4':\n\t\tcase 'h5':\n\t\tcase 'h6':\n\t\t\treturn inner ? `*${inner}*\\n` : '\\n';\n\n\t\tcase 'ul':\n\t\tcase 'ol':\n\t\t\treturn inner;\n\n\t\tcase 'li':\n\t\t\treturn `• ${inner.trimEnd()}\\n`;\n\n\t\tcase 'blockquote':\n\t\t\treturn (\n\t\t\t\tinner\n\t\t\t\t\t.split('\\n')\n\t\t\t\t\t.map((l) => (l ? `> ${l}` : ''))\n\t\t\t\t\t.join('\\n') + '\\n'\n\t\t\t);\n\n\t\tcase 'body':\n\t\tdefault:\n\t\t\treturn inner;\n\t}\n}\n\nfunction serializeChildren(el: Element): string {\n\treturn Array.from(el.childNodes).map(serializeNode).join('');\n}\n\n// ---------------------------------------------------------------------------\n// SSR fallback — regex-based, best-effort for simple markup\n// ---------------------------------------------------------------------------\n\nfunction ssrFallback(html: string): string {\n\treturn html\n\t\t.replace(/<strong[^>]*>([\\s\\S]*?)<\\/strong>/gi, '*$1*')\n\t\t.replace(/<b[^>]*>([\\s\\S]*?)<\\/b>/gi, '*$1*')\n\t\t.replace(/<em[^>]*>([\\s\\S]*?)<\\/em>/gi, '_$1_')\n\t\t.replace(/<i[^>]*>([\\s\\S]*?)<\\/i>/gi, '_$1_')\n\t\t.replace(/<s[^>]*>([\\s\\S]*?)<\\/s>/gi, '~$1~')\n\t\t.replace(/<del[^>]*>([\\s\\S]*?)<\\/del>/gi, '~$1~')\n\t\t.replace(/<code[^>]*>([\\s\\S]*?)<\\/code>/gi, '`$1`')\n\t\t.replace(/<a[^>]*>([\\s\\S]*?)<\\/a>/gi, '$1')\n\t\t.replace(/<p[^>]*>\\s*<br\\s*\\/?>\\s*<\\/p>/gi, '\\n')\n\t\t.replace(/<br\\s*\\/?>/gi, '\\n')\n\t\t.replace(/<\\/p>/gi, '\\n')\n\t\t.replace(/<\\/div>/gi, '\\n')\n\t\t.replace(/<\\/h[1-6]>/gi, '\\n')\n\t\t.replace(/<li[^>]*>/gi, '• ')\n\t\t.replace(/<\\/li>/gi, '\\n')\n\t\t.replace(/<[^>]+>/g, '')\n\t\t.replace(/&amp;/g, '&')\n\t\t.replace(/&lt;/g, '<')\n\t\t.replace(/&gt;/g, '>')\n\t\t.replace(/&nbsp;/g, ' ')\n\t\t.trim();\n}\n"],"names":["toWhatsAppText","html","document","serializeNode","DOMParser","parseFromString","body","trim","replace","ssrFallback","node","nodeType","Node","TEXT_NODE","textContent","_a","ELEMENT_NODE","el","tag","tagName","toLowerCase","inner","Array","from","childNodes","map","join","serializeChildren","length","_c","_b","firstChild","trimEnd","split","l"],"mappings":"AAcM,SAAUA,EAAeC,GAC9B,IAAKA,EAAM,MAAO,GAElB,GAAwB,oBAAbC,SAA0B,CAEpC,OAAOC,GADK,IAAIC,WAAYC,gBAAgBJ,EAAM,aACzBK,MAAMC,MAC/B,CAGD,OAwFD,SAAqBN,GACpB,OAAOA,EACLO,QAAQ,sCAAuC,QAC/CA,QAAQ,4BAA6B,QACrCA,QAAQ,8BAA+B,QACvCA,QAAQ,4BAA6B,QACrCA,QAAQ,4BAA6B,QACrCA,QAAQ,gCAAiC,QACzCA,QAAQ,kCAAmC,QAC3CA,QAAQ,4BAA6B,MACrCA,QAAQ,kCAAmC,MAC3CA,QAAQ,eAAgB,MACxBA,QAAQ,UAAW,MACnBA,QAAQ,YAAa,MACrBA,QAAQ,eAAgB,MACxBA,QAAQ,cAAe,MACvBA,QAAQ,WAAY,MACpBA,QAAQ,WAAY,IACpBA,QAAQ,SAAU,KAClBA,QAAQ,QAAS,KACjBA,QAAQ,QAAS,KACjBA,QAAQ,UAAW,KACnBD,MACH,CA/GQE,CAAYR,EACpB,CAMA,SAASE,EAAcO,aACtB,GAAIA,EAAKC,WAAaC,KAAKC,UAC1B,OAAuB,UAAhBH,EAAKI,mBAAW,IAAAC,EAAAA,EAAI,GAE5B,GAAIL,EAAKC,WAAaC,KAAKI,aAAc,MAAO,GAEhD,MAAMC,EAAKP,EACLQ,EAAMD,EAAGE,QAAQC,cACjBC,EAiEP,SAA2BJ,GAC1B,OAAOK,MAAMC,KAAKN,EAAGO,YAAYC,IAAItB,GAAeuB,KAAK,GAC1D,CAnEeC,CAAkBV,GAEhC,OAAQC,GACP,IAAK,SACL,IAAK,IACJ,OAAOG,EAAQ,IAAIA,KAAW,GAE/B,IAAK,KACL,IAAK,IACJ,OAAOA,EAAQ,IAAIA,KAAW,GAE/B,IAAK,IACL,IAAK,MACL,IAAK,SACJ,OAAOA,EAAQ,IAAIA,KAAW,GAE/B,IAAK,OACJ,OAAOA,EAAQ,KAAKA,MAAY,GAEjC,IAAK,MACJ,OAAOA,EAAQ,SAASA,UAAgB,GAEzC,IAAK,IAsBL,IAAK,KACL,IAAK,KAcL,IAAK,OACL,QACC,OAAOA,EApCR,IAAK,KACJ,MAAO,KAER,IAAK,IACL,IAAK,MAIJ,OAF0B,IAAzBJ,EAAGO,WAAWI,QACyC,QAApB,QAAnCC,EAA0B,QAA1BC,EAACb,EAAGc,kBAAsB,IAAAD,OAAA,EAAAA,EAAEX,eAAO,IAAAU,OAAA,EAAAA,EAAET,eACjB,KAAOC,KAAWA,MAAY,KAGpD,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACJ,OAAOA,EAAQ,IAAIA,OAAa,KAMjC,IAAK,KACJ,WAAYA,EAAMW,cAEnB,IAAK,aACJ,OACCX,EACEY,MAAM,MACNR,KAAKS,GAAOA,EAAI,KAAKA,IAAM,KAC3BR,KAAK,MAAQ,KAOnB"}
@@ -1,3 +1,4 @@
1
+ /// <reference types="react" />
1
2
  export declare const Menus: ({
2
3
  displayName: string;
3
4
  key: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bikdotai/bik-component-library",
3
- "version": "0.0.807-beta.0",
3
+ "version": "0.0.807-beta.2",
4
4
  "description": "Bik Component Library",
5
5
  "repository": {
6
6
  "type": "git",