{"version":3,"sources":["webpack:///./ClientApp/services/Localizer.tsx","webpack:///./ClientApp/features/search/RocHawkConfig.ts","webpack:///./ClientApp/features/tracking/trackers/commerce/hawksearch/tracking-commerce.ts","webpack:///./ClientApp/shared/polyfills/customEvent.js","webpack:///./ClientApp/shared/hooks/useInViewOnce.ts","webpack:///./ClientApp/util/StringUtil.ts","webpack:///./ClientApp/shared/components/hawksearch/net/HawkClient.ts","webpack:///./ClientApp/services/ServerData.ts","webpack:///./ClientApp/shared/components/Spinner.tsx","webpack:///./ClientApp/services/AxiosHelper.ts","webpack:///./ClientApp/features/tracking/trackers/commerce/hawksearch/hawk-search-commerce-tracker.ts","webpack:///./ClientApp/shared/edit/InlineAlert.tsx","webpack:///./ClientApp/shared/hooks/useRocEventHandler.tsx","webpack:///./ClientApp/shared/components/svg/XSVG.tsx","webpack:///./ClientApp/services/UserData.ts","webpack:///./ClientApp/shared/util/ErrorBoundary.tsx","webpack:///./ClientApp/shared/util/AccountUrls.ts","webpack:///./ClientApp/features/tracking/trackers/hawksearch/tracking.ts","webpack:///./ClientApp/shared/polyfills/getAttributeNames.js","webpack:///./ClientApp/shared/util/ApplicationInit.tsx","webpack:///./ClientApp/shared/components/hawksearch/util/Constants.ts","webpack:///./ClientApp/shared/components/hawksearch/helpers/Cookies.ts","webpack:///./ClientApp/shared/components/commerce/ProductPricing.tsx","webpack:///./ClientApp/shared/hooks/useDelayedDisplay.tsx","webpack:///./ClientApp/shared/util/events/rocEventUtils.ts","webpack:///../Roc.SharedClientApp/types/commerce/display-price.ts","webpack:///./ClientApp/features/commerce/product-details/types.ts","webpack:///./ClientApp/shared/components/hawksearch/models/Recommendation/Request.ts","webpack:///./ClientApp/shared/components/hawksearch/models/Recommendation/Item.ts","webpack:///./ClientApp/shared/components/hawksearch/models/Recommendation/Widget.ts","webpack:///./ClientApp/shared/components/hawksearch/models/Recommendation/Response.ts","webpack:///./ClientApp/shared/components/hawksearch/helpers/hawkRecommendationContext.ts","webpack:///./ClientApp/features/hawk-recommendations/PlaceholderImage.tsx","webpack:///./ClientApp/features/hawk-recommendations/Image.tsx","webpack:///./ClientApp/features/hawk-recommendations/items/commerce/ProductPriceRenderer.tsx","webpack:///./ClientApp/features/hawk-recommendations/items/shared/OptionalAnchor.tsx","webpack:///./ClientApp/features/hawk-recommendations/items/commerce/Item.tsx","webpack:///./ClientApp/features/hawk-recommendations/widgets/commerce/Carousel.tsx","webpack:///./ClientApp/features/hawk-recommendations/Loader.tsx","webpack:///./ClientApp/features/hawk-recommendations/index.tsx"],"names":["LocalizerResources","isAlreadyLogged","initializeLocalizerResources","windowWithResources","window","__ROC_LOCALIZER_RESOURCES__","Array","isArray","forEach","obj","Object","keys","key","Localizer","replaceStrings","length","console","warn","resource","replace","match","index","LocalizedSpan","props","resourceKey","args","localizedString","data-testid","toKebabCase","dangerouslySetInnerHTML","__html","searchState","__ROC_SEARCH_STATE__","RocHawkConfig","apiUrl","searchEndpoint","clientGuid","trackingKey","searchPageUrl","dashboardUrl","Constants","searchBoxPlaceholder","trackingUrl","recommendationUrl","recommendationEndpoint","enableRemovingDashesFromSearchKeyword","CommerceEventTrackingType","CommercePageType","CommerceSuggestType","trackCommerce","eventName","toLocaleLowerCase","orderNo","itemList","total","subTotal","tax","currency","payload","EventType","sale","EventData","preparePayload","OrderNo","ItemList","Total","Tax","SubTotal","Currency","makeRequest","uniqueId","price","quantity","addToCart","UniqueId","Quantity","Price","trackAddToCart","itemsList","add2CartMultiple","ItemsList","TrackAddToCartMultiple","value","rate","Value","trackRate","CustomEvent","event","params","bubbles","cancelable","detail","undefined","evt","document","createEvent","initCustomEvent","prototype","Event","useInViewOnce","makeIterator","options","inViewHookResponse","useInView","useState","viewed","setViewed","useEffect","inView","newResponse","Symbol","iterator","trim","toCamelCase","word","toLowerCase","toUpperCase","stripHtml","html","tmp","createElement","innerHTML","textContent","innerText","addEllipsis","text","cutoff","substring","trimString","HawkClient","config","this","baseUrl","searchUrl","autocompleteUrl","recommendationWidgetUrl","compareItemsURL","request","cancellationToken","AxiosHelper","post","cancelToken","result","data","ServerData","windowWithServerData","__ROC_SERVER_DATA__","initializeServerData","Spinner","light","waitMs","align","block","parentCentered","useDelayedDisplay","spinner","className","classnames","axios","create","defaults","headers","common","interceptors","use","method","getCsrfToken","csrfToken","RequestVerificationToken","addUnauthorizedAccessInterceptor","history","response","error","status","location","AccountUrls","Login","encodeURIComponent","pathname","Promise","reject","convertOrderToHawkSearchItems","order","resolveItemPrice","item","unitPrice","salePrice","rawValue","basePrice","recipients","reduce","items","recipient","map","product","productGroupId","id","itemPrice","addProductToContext","HawkSearch","Context","add","toString","addProductAttributesToContext","hawkAttributes","attribute","name","remove","addMultipleProductAttributesToContext","push","selectionsToHawkAttributes","selections","selection","field","values","find","s","checked","label","convertProductSelectionToHawksearchAttributes","setup","addRocEventHandler","Tracking","track","pageType","cart","productId","rating","orderCode","snapshotCurrencyISO","subtotal","adjustedQuantity","url","HawkSearchTrackingId","trackingId","productDetails","summary","InlineAlert","title","defaultProps","children","theme","isTitleOnOwnRow","isCollapsed","onCollapse","message","axiosError","isAxiosError","type","onClick","dispatchRocEvent","eventType","dispatchEvent","useRocEventHandler","eventHandler","deps","removeHandlerCallback","XSVG","rest","viewBox","focusable","aria-hidden","d","userDataPromise","getUserData","get","getUserDataNoCache","userData","requestToken","ErrorBoundary","lastRefreshedTimestamp","Date","parseInt","localStorage","getItem","getTime","setItem","reload","setState","state","renderError","React","Component","renderProps","BaseUrl","ACCOUNT_URL_BASE","ACCOUNT_LOGIN_URL","Login2fa","ACCOUNT_LOGIN_WITH_2FA_URL","Register","ACCOUNT_REGISTER_URL","ForgotPassword","ACCOUNT_FORGOT_PASSWORD_URL","LoginWithRecoveryCode","ACCOUNT_LOGIN_WITH_RECOVERY_CODE_URL","Logout","ACCOUNT_LOGOUT_URL","OrganizationReview","ACCOUNT_ORGANIZATION_REVIEW_URL","OrganizationSelector","ACCOUNT_ORGANIZATION_SELECTOR_URL","ExternalLogout","EventTrackingType","PageType","SuggestType","SearchType","createGuid","i","substr","Math","floor","random","join","input","JSON","stringify","utf8Bytes","TextEncoder","encode","btoa","String","fromCharCode","TrackingUrl","visitId","getCookie","visitorId","isNewVisitor","setCookie","setTime","toUTCString","getVisitorExpiry","assign","ClientGuid","VisitId","VisitorId","TrackingProperties","CustomDictionary","CustomContext","then","catch","init","initCustomEvents","readyState","setTimeout","addEventListener","ContextDictionary","hasOwnProperty","existingValue","documentElement","clientHeight","clientWidth","pageLoad","PageTypeId","RequestPath","Qs","search","ViewportHeight","ViewportWidth","typeId","Initial","queryId","QueryId","TrackingId","TypeId","trackSearchTracking","click","Url","trackClick","bannerId","campaignId","bannerClick","CampaignId","BannerId","bannerImpression","trackBannerImpression","keyword","suggestType","itemName","autoCompleteClick","Keyword","Name","widgetGuid","itemIndex","requestId","recommendationClick","ItemIndex","RequestId","WidgetGuid","trackRecommendationClick","Element","getAttributeNames","attributes","getDataPropsFromAttributes","element","filter","startsWith","attributeName","getAttribute","initReactApp","getReactElement","elementId","getElementById","ReactDOM","render","Suspense","fallback","initReactAppByAttribute","elements","querySelectorAll","defaultApiUrl","defaultDashboardUrl","defaultSearchUrl","defaultAutocompleteUrl","defaultSearchPageUrl","defaultCompareItemsURL","defaultRecommendationUrl","getVisitExpiry","nameEQ","ca","cookie","split","charAt","indexOf","expiry","expires","ProductPricing","displayPrice","inline","testId","roundValue","renderResult","css","priceClass","base","normalPrice","crossedOutPrice","highlightedPrice","GetCssClasses","displayRule","PriceDisplayRule","Missing","Normal","basePriceClass","VariantPriceComponent","renderNormalPrice","AmbiguousRange","roundedPrice","toFixed","FormatAmbiguousPriceSpan","unitName","unit","renderAmbiguousPrice","Error","FormatPrice","FormatPriceSpan","priceRange","from","to","display","setDisplay","timeout","clearTimeout","handler","removeEventListener","getInitialProductDetailsState","__ROC_COMMERCE_PRODUCT_DETAILS__","InputAttributeType","ProductType","AddToCartExceptionCode","entries","Item","Widget","recommendationItems","r","Response","widgetItems","__ROC_HAWK_RECOMMENDATION_CONTEXT_OBJECT__","HawkRecommendation","PlaceholderImage","showSpinner","Image","imageUrl","hasImage","setHasImage","imageLoaded","setImageLoaded","style","overflow","width","height","onLoad","onError","role","src","alt","ProductPriceRenderer","displayPriceStringified","customDict","parse","OptionalAnchor","href","target","DefaultItem","classNameSuffix","data-hawk-modelname","modelName","data-haw-modeltype","modelType","brand","Carousel","widget","widgetData","renderHTML","currentInstanceId","useRef","uuid","current","sliderRef","threshold","ref","tnsPromise","module","tns","initializeSlider","destroy","currentSliderDiv","getTinySliderInstance","container","slideBy","controls","mouseDrag","gutter","lazyload","loop","responsive","768","1024","1200","widgeTitle","ItemComponent","customComponent","getWidgetItemComponent","widgetCssClass","dispatchWidgetClickEvent","initialProductState","Loader","client","recommendations","setRecommendations","loading","setLoading","setHawkAttributes","getRecommendations","widgetUids","getRecommendationPlaceholders","recommendationResults","contextProperties","customProperties","getRecommendationWidgetItems","enablePreview","isInPreview","w","matchedResult","f","hasItems","isCancel","isSuccess","RecommendationResponse","cts","CancelToken","source","token","cancel","newHawkAttributes","targetElements","Fragment","el","WidgetContainer","renderHtml","WidgetComponent","getWidgetComponent","createPortal","isLoading","guid"],"mappings":"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","file":"hawk-recommendations.2de07459.js","sourcesContent":["import { AddressResourceKeys } from 'features/address-book/resources';\r\nimport { ContactFormResourceKeys } from 'features/contact-form/resources';\r\nimport { CreatePasswordResourceKeys } from 'features/create-password/resources';\r\nimport { LoginWith2faResourceKeys } from 'features/login-with-2fa/resources';\r\nimport { LoginWithRecoveryCodeResourceKeys } from 'features/login-with-recovery-code/resources';\r\nimport { LoginResourceKeys } from 'features/login/resources';\r\nimport { MyAccountResourceKeys } from 'features/my-account/resources';\r\nimport { ResetPasswordResourceKeys } from 'features/reset-password/resources';\r\nimport { SubmitQuestionResourceKeys } from 'features/submit-question/resources';\r\nimport * as React from 'react';\r\nimport { toKebabCase } from 'util/StringUtil';\r\n\r\n// #region Commerce\r\nimport { CommerceResourceKeys } from 'features/commerce/CommerceResourceKeys';\r\n// #endregion\r\n\r\n// #region HCL\r\nimport { QuickBagsResourceKeys } from 'features/hcl/quick-bags/resources';\r\nimport { QuickLabelsResourceKeys } from 'features/hcl/quick-labels/resources';\r\nimport { ProductCatalogsResourceKeys } from 'features/hcl/product-catalogs/resources';\r\nimport { FileUploadResourceKeys } from 'features/hcl/file-upload/resources';\r\nimport { NewsletterKeys } from 'features/hcl/newsletter-signup/resources';\r\n// #endregion\r\n\r\n/**\r\n * Type that will hold all the global localization keys\r\n */\r\ntype LocalizerGlobalResourceKeys =\r\n\t| 'Success'\r\n\t| 'OfTotalPages'\r\n\t| 'Cancel'\r\n\t| 'Confirm'\r\n\t| 'FirstName'\r\n\t| 'LastName'\r\n\t| 'Email'\r\n\t| 'Username'\r\n\t| 'Amount'\r\n\t| 'NameOnCard'\r\n\t| 'CardNumber'\r\n\t| 'ExpDate'\r\n\t| 'ExpMonth'\r\n\t| 'ExpYear'\r\n\t| 'Expires'\r\n\t| 'Expired'\r\n\t| 'SecurityCode'\r\n\t| 'Submit'\r\n\t| 'Save'\r\n\t| 'ZipCode'\r\n\t| 'Remove'\r\n\t| 'Removed'\r\n\t| 'Update'\r\n\t| 'Undo'\r\n\t| 'Cancel'\r\n\t| 'Enter'\r\n\t| 'Close'\r\n\t| 'SortBy'\r\n\t| 'PleaseWait'\r\n\t| 'Unknown'\r\n\t| 'Yes'\r\n\t| 'No'\r\n\t| 'Delete'\r\n\t| 'Update'\r\n\t| 'SaveAndContinueButtonText'\r\n\t| 'SaveAndContinue'\r\n\t| 'Continue'\r\n\t| 'SaveErrorMessage'\r\n\t| 'Edit'\r\n\t| 'ErrorMessageGenericTitle'\r\n\t| 'CheckEnteredValues'\r\n\t| 'ErrorMessageForbidden'\r\n\t| 'ErrorMessageNetwork'\r\n\t| 'ErrorOccurredSubmittingTheForm'\r\n\t| 'UnexpectedErrorOccurred'\r\n\t| 'Login'\r\n\t| 'ReturnToShipping'\r\n\t| 'BreadcrumbsLabel'\r\n\t| 'Other'\r\n\t| 'RememberMe'\r\n\t| 'ForgotYourPassword'\r\n\t| 'RegisterNewUserLinkText'\r\n\t| 'LoginPageTitleText'\r\n\t| 'ForgotPasswordPageTitle'\r\n\t| 'ForgotPasswordConfirmationPageTitle'\r\n\t| 'ForgotPasswordConfirmation'\r\n\t| 'Optional'\r\n\t| 'SearchBoxPlaceholder'\r\n\t| 'XOutOfYStars'\r\n\t| 'XToYOfZ'\r\n\t| 'ModalLabel'\r\n\t| 'RequiredFields'\r\n\t| 'Status'\r\n\t| 'Version'\r\n\t| 'CreatedOn'\r\n\t| 'CreatedBy'\r\n\t| 'ModifiedOn'\r\n\t| 'ModifiedBy'\r\n\t| 'OpenStatusInformation'\r\n\t| 'CloseStatusInformation'\r\n\t| 'SearchFilter'\r\n\t| 'Pagination'\r\n\t| 'Previous'\r\n\t| 'Next'\r\n\t| 'ClearFilter';\r\n\r\n/**\r\n * Type that will hold all the localization keys\r\n */\r\nexport type LocalizerResourceKey =\r\n\t| LocalizerGlobalResourceKeys\r\n\t| LoginResourceKeys\r\n\t| ContactFormResourceKeys\r\n\t// #region Commerce\r\n\t| CommerceResourceKeys\r\n\t// #endregion\r\n\t| ResetPasswordResourceKeys\r\n\t| CreatePasswordResourceKeys\r\n\t| SubmitQuestionResourceKeys\r\n\t| ResetPasswordResourceKeys\r\n\t| CreatePasswordResourceKeys\r\n\t| MyAccountResourceKeys\r\n\t| LoginWith2faResourceKeys\r\n\t| LoginWithRecoveryCodeResourceKeys\r\n\t| AddressResourceKeys\r\n\t// #region HCL\r\n\t| QuickBagsResourceKeys\r\n\t| QuickLabelsResourceKeys\r\n\t| ProductCatalogsResourceKeys\r\n\t| NewsletterKeys\r\n\t| FileUploadResourceKeys;\r\n// #endregion\r\n\r\n/**\r\n * Interface for the resources\r\n *\r\n * @export\r\n * @interface LocalizerResource\r\n */\r\ninterface LocalizerResource {\r\n\t[id: string]: string;\r\n}\r\n\r\n/**\r\n * Extends Window with a property that will hold the localizer resources\r\n *\r\n * @interface WindowWithResources\r\n * @extends {Window}\r\n */\r\nexport interface WindowWithResources extends Window {\r\n\t__ROC_LOCALIZER_RESOURCES__?: LocalizerResource[];\r\n}\r\n\r\n/**\r\n * Main object that will hold all the localized resources\r\n */\r\nconst LocalizerResources: LocalizerResource = {};\r\n\r\n/**\r\n * To prevent redundant logging\r\n */\r\nconst isAlreadyLogged: Record = {};\r\n\r\n/**\r\n * Initializer function that will populate the main localized resources object\r\n */\r\nfunction initializeLocalizerResources() {\r\n\tconst windowWithResources = window as WindowWithResources;\r\n\r\n\tif (\r\n\t\twindowWithResources &&\r\n\t\twindowWithResources.__ROC_LOCALIZER_RESOURCES__ &&\r\n\t\tArray.isArray(windowWithResources.__ROC_LOCALIZER_RESOURCES__)\r\n\t) {\r\n\t\twindowWithResources.__ROC_LOCALIZER_RESOURCES__.forEach((obj) => {\r\n\t\t\tfor (const key of Object.keys(obj)) {\r\n\t\t\t\tLocalizerResources[key] = obj[key];\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n}\r\n\r\n/**\r\n * Function that can be used to load the localized strings with support to parameter replacements\r\n *\r\n * @export\r\n * @param {string} key\r\n * @param {...string[]} replaceStrings\r\n * @returns\r\n */\r\nexport function Localizer(\r\n\tkey: TResourceKey,\r\n\t...replaceStrings: string[]\r\n) {\r\n\tif (Object.keys(LocalizerResources).length === 0) {\r\n\t\tinitializeLocalizerResources();\r\n\t}\r\n\r\n\tif (!LocalizerResources || !LocalizerResources[key]) {\r\n\t\t// if running in a test environment, just skip any warnings.\r\n\t\tif (process.env.NODE_ENV !== 'test') {\r\n\t\t\tif (!isAlreadyLogged[key]) {\r\n\t\t\t\tconsole.warn(key, 'Localizer Resource not found. Key will be used instead.');\r\n\t\t\t\tisAlreadyLogged[key] = true;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn key;\r\n\t}\r\n\r\n\tconst resource = LocalizerResources[key];\r\n\r\n\tif (!replaceStrings) {\r\n\t\treturn resource;\r\n\t}\r\n\r\n\treturn resource.replace(/{(\\d+)}/g, (match: string, index: number) => {\r\n\t\treturn replaceStrings[index] ? replaceStrings[index] : '';\r\n\t});\r\n}\r\n\r\n/**\r\n * Interface for the LocalizedSpan component\r\n *\r\n * @interface LocalizedSpanProps\r\n */\r\ninterface LocalizedSpanProps {\r\n\tresourceKey: LocalizerResourceKey;\r\n\targs?: string[];\r\n}\r\n\r\n/**\r\n * Component responsible for the initialization of the react app\r\n */\r\nexport function LocalizedSpan(props: LocalizedSpanProps) {\r\n\tconst { resourceKey, args = [] } = props;\r\n\tconst localizedString = Localizer(resourceKey, ...args);\r\n\r\n\treturn (\r\n\t\t\r\n\t);\r\n}\r\n","import { HawkSearchConfig } from 'shared/components/hawksearch/types/HawkSearchConfig';\r\nimport * as Constants from 'util/Constants';\r\nimport { Localizer } from 'services/Localizer';\r\n\r\nconst searchState = (window as any).__ROC_SEARCH_STATE__;\r\n\r\nconst RocHawkConfig: HawkSearchConfig = {\r\n\tapiUrl: searchState.searchEndpoint as string,\r\n\tclientGuid: searchState.trackingKey as string,\r\n\tsearchPageUrl: (searchState.searchPageUrl as string) || '/search',\r\n\tdashboardUrl: (searchState.dashboardUrl as string) || Constants.defaultDashboardUrl,\r\n\tsearchBoxPlaceholder: Localizer('SearchBoxPlaceholder'),\r\n\ttrackingUrl: searchState.trackingUrl as string,\r\n\t/* #region Commerce */\r\n\trecommendationUrl: searchState.recommendationEndpoint as string,\r\n\tenableRemovingDashesFromSearchKeyword: searchState.enableRemovingDashesFromSearchKeyword as boolean,\r\n\t/* #endregion */\r\n};\r\n\r\nexport default RocHawkConfig;\r\n","import { ExtractEventParameters } from 'shared/events';\r\nimport { makeRequest, preparePayload } from '../../hawksearch/tracking';\r\n\r\nexport enum CommerceEventTrackingType {\r\n\taddToCart = 4,\r\n\trate = 5,\r\n\tsale = 6,\r\n\tadd2CartMultiple = 14,\r\n}\r\n\r\n/**\r\n * The page type\r\n */\r\nexport enum CommercePageType {\r\n\t/**\r\n\t * Item detail page (i.e. PDP)\r\n\t */\r\n\titem = 1,\r\n\t/**\r\n\t * Shopping Cart Page\r\n\t */\r\n\tcart = 3,\r\n\t/**\r\n\t * Order Confirmation Page\r\n\t */\r\n\torder = 4,\r\n}\r\n\r\nexport enum CommerceSuggestType {\r\n\tTopCategories = 2,\r\n\tTopProductMatches = 3,\r\n}\r\n\r\ntype CommerceHawkEvents =\r\n\t| ({ name: 'sale' } & TrackSaleArgs)\r\n\t| ({ name: 'add2cart' } & TrackAddToCartArgs)\r\n\t| ({ name: 'add2cartmultiple' } & TrackAddToCartMultipleArgs)\r\n\t| ({ name: 'rate' } & TrackRateArgs);\r\n\r\nexport type CommerceHawkEventType = CommerceHawkEvents['name'];\r\n\r\nexport function trackCommerce(\r\n\teventName: T,\r\n\targs: ExtractEventParameters,\r\n) {\r\n\tswitch (eventName.toLocaleLowerCase()) {\r\n\t\tcase 'sale':\r\n\t\t\t//HawkSearch.Tracking.track('sale', {orderNo: 'order_123',itemList: [{uniqueid: '123456789', itemPrice: 12.99, quantity: 2}], total: 25.98, subTotal: 22, tax: 3.98, currency: 'USD'});\r\n\t\t\treturn trackSale((args as unknown) as TrackSaleArgs);\r\n\t\tcase 'add2cart':\r\n\t\t\t//HawkSearch.Tracking.track('add2cart',{uniqueId: '123456789', price: 19.99, quantity: 3, currency: 'USD'});\r\n\t\t\treturn trackAddToCart((args as unknown) as TrackAddToCartArgs);\r\n\t\tcase 'add2cartmultiple':\r\n\t\t\t//HawkSearch.Tracking.track('add2cartmultiple', [{uniqueId: '123456789',price: 15.97,quantity: 1,currency: 'USD'},{uniqueId: '987465321', price: 18.00, quantity: 1, currency: 'USD'}]);\r\n\t\t\treturn TrackAddToCartMultiple((args as unknown) as TrackAddToCartMultipleArgs);\r\n\t\tcase 'rate':\r\n\t\t\t//HawkSearch.Tracking.track('rate', {uniqueId: '123456789',value: 3.00});\r\n\t\t\treturn trackRate((args as unknown) as TrackRateArgs);\r\n\t}\r\n}\r\n\r\nexport type TrackSaleItemArgs = {\r\n\t/**\r\n\t * Represents the unique identifier of a product. This should correspond to the value of the field set up as the primary key in the fields section of Hawksearch dashboard\r\n\t */\r\n\tuniqueId: string;\r\n\t/**\r\n\t * Represents a single item price\r\n\t */\r\n\titemPrice: number;\r\n\t/**\r\n\t * The number of items being added to the cart\r\n\t */\r\n\tquantity: number;\r\n};\r\n\r\ntype TrackSaleArgs = {\r\n\t/**\r\n\t * The alphanumeric value representing the order number\r\n\t */\r\n\torderNo: string;\r\n\t/**\r\n\t * Is an array of objects that stores information about items. To see object properties check Sale Item Info Model below.\r\n\t */\r\n\titemList: TrackSaleItemArgs[];\r\n\t/**\r\n\t * The actual order total amount\r\n\t */\r\n\ttotal?: number;\r\n\t/**\r\n\t * The order the sub total amoun\r\n\t */\r\n\tsubTotal?: number;\r\n\t/**\r\n\t * The tax value\r\n\t */\r\n\ttax?: number;\r\n\t/**\r\n\t * The actual currency in ISO format\r\n\t */\r\n\tcurrency?: string;\r\n};\r\n\r\nfunction trackSale({ orderNo, itemList, total, subTotal, tax, currency }: TrackSaleArgs) {\r\n\tconst payload = {\r\n\t\tEventType: CommerceEventTrackingType.sale,\r\n\t\tEventData: preparePayload({\r\n\t\t\tOrderNo: orderNo,\r\n\t\t\tItemList: itemList,\r\n\t\t\tTotal: total,\r\n\t\t\tTax: tax,\r\n\t\t\tSubTotal: subTotal,\r\n\t\t\tCurrency: currency,\r\n\t\t}),\r\n\t};\r\n\r\n\tmakeRequest(payload);\r\n}\r\n\r\nexport type TrackAddToCartArgs = {\r\n\t/**\r\n\t * Represents the unique identifier of a product. This should correspond to the value of the field set up as the primary key in the fields section of Hawksearch dashboard\r\n\t */\r\n\tuniqueId: string;\r\n\t/**\r\n\t * Represents a single item price\r\n\t */\r\n\tprice: number;\r\n\t/**\r\n\t * The number of items being added to the cart\r\n\t */\r\n\tquantity: number;\r\n\t/**\r\n\t * Actual currency in ISO format\r\n\t */\r\n\tcurrency: string;\r\n};\r\n\r\nfunction trackAddToCart({ uniqueId, price, quantity, currency }: TrackAddToCartArgs) {\r\n\tconst payload = {\r\n\t\tEventType: CommerceEventTrackingType.addToCart,\r\n\t\tEventData: preparePayload({\r\n\t\t\tUniqueId: uniqueId,\r\n\t\t\tQuantity: quantity,\r\n\t\t\tPrice: price,\r\n\t\t\tCurrency: currency,\r\n\t\t}),\r\n\t};\r\n\r\n\tmakeRequest(payload);\r\n}\r\n\r\ntype TrackAddToCartMultipleArgs = {\r\n\t/**\r\n\t * Is an array of objects that stores information about items\r\n\t */\r\n\titemsList: TrackAddToCartArgs[];\r\n};\r\n\r\nfunction TrackAddToCartMultiple({ itemsList }: TrackAddToCartMultipleArgs) {\r\n\tconst payload = {\r\n\t\tEventType: CommerceEventTrackingType.add2CartMultiple,\r\n\t\tEventData: preparePayload({\r\n\t\t\tItemsList: itemsList,\r\n\t\t}),\r\n\t};\r\n\r\n\tmakeRequest(payload);\r\n}\r\n\r\ntype TrackRateArgs = {\r\n\t/**\r\n\t * The unique identifier of an item. In many cases the uniqueId is different than SKU.\r\n\t */\r\n\tuniqueId: string;\r\n\t/**\r\n\t * Represents a user’s rating for an item. The decimal value must be between 1 and 5.\r\n\t */\r\n\tvalue: number;\r\n};\r\n\r\nfunction trackRate({ uniqueId, value }: TrackRateArgs) {\r\n\tconst payload = {\r\n\t\tEventType: CommerceEventTrackingType.rate,\r\n\t\tEventData: preparePayload({\r\n\t\t\tUniqueId: uniqueId,\r\n\t\t\tValue: value,\r\n\t\t}),\r\n\t};\r\n\tmakeRequest(payload);\r\n}\r\n","// source: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent\r\n(function () {\r\n\tif (typeof window.CustomEvent === 'function') {\r\n\t\treturn false;\r\n\t}\r\n\r\n\tfunction CustomEvent(event, params) {\r\n\t\tparams = params || { bubbles: false, cancelable: false, detail: undefined };\r\n\t\t// eslint-disable-next-line\r\n\t\tvar evt = document.createEvent('CustomEvent');\r\n\t\tevt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);\r\n\t\treturn evt;\r\n\t}\r\n\r\n\tCustomEvent.prototype = window.Event.prototype;\r\n\r\n\twindow.CustomEvent = CustomEvent;\r\n})();\r\n","import { useInView, IntersectionOptions, InViewHookResponse } from 'react-intersection-observer';\r\nimport { useEffect, useState } from 'react';\r\n\r\n/**\r\n * Wrapper hook to useInView so that it only triggers once. Useful for lazy-loaded content that\r\n * doesn't need to change once it's out of view.\r\n */\r\nexport function useInViewOnce(options: IntersectionOptions = {}): InViewHookResponse {\r\n\tconst inViewHookResponse = useInView(options);\r\n\tconst [viewed, setViewed] = useState(false);\r\n\r\n\tuseEffect(() => {\r\n\t\tif (inViewHookResponse.inView) {\r\n\t\t\tsetViewed(true);\r\n\t\t}\r\n\t}, [inViewHookResponse.inView]);\r\n\r\n\tconst newResponse: InViewHookResponse = {\r\n\t\t...inViewHookResponse,\r\n\t\tinView: viewed,\r\n\t\t[0]: inViewHookResponse[0],\r\n\t\t[1]: viewed,\r\n\t\t[2]: inViewHookResponse[2],\r\n\t};\r\n\r\n\tfunction* makeIterator() {\r\n\t\tyield newResponse[0];\r\n\t\tyield newResponse[1];\r\n\t\tyield newResponse[2];\r\n\t}\r\n\r\n\tnewResponse[Symbol.iterator] = makeIterator;\r\n\r\n\treturn newResponse;\r\n}\r\n","// These functions may be potentially innaccurate in certain locales that use differing amounts of characters in different cases\r\n\r\n/**\r\n * Tests if a string includes another if casing is ignored\r\n * @param thisString The string to test\r\n * @param otherString The potentially included string being tested for\r\n */\r\nexport function stringWeaklyIncludes(thisString: string, otherString: string) {\r\n\treturn thisString.toLocaleLowerCase().includes(otherString.toLocaleLowerCase());\r\n}\r\n\r\n/**\r\n * Tests if a string starts with another if casing is ignored\r\n * @param thisString The string to test\r\n * @param otherString The potentially included string being tested for\r\n */\r\nexport function stringWeaklyStartsWith(thisString: string, otherString: string) {\r\n\treturn thisString.toLocaleLowerCase().startsWith(otherString.toLocaleLowerCase());\r\n}\r\n\r\n/**\r\n * Tests if a string ends with another if casing is ignored\r\n * @param thisString The string to test\r\n * @param otherString The potentially included string being tested for\r\n */\r\nexport function stringWeaklyEndsWith(thisString: string, otherString: string) {\r\n\treturn thisString.toLocaleLowerCase().endsWith(otherString.toLocaleLowerCase());\r\n}\r\n\r\n/**\r\n * Converts the first character in a string to upper-case. Will not work for all languages (for example Dutch).\r\n *\r\n * @export\r\n * @param {string} thisString\r\n * @returns\r\n */\r\nexport function firstCharacterToUpper(thisString: string) {\r\n\tif (!thisString) {\r\n\t\treturn '';\r\n\t}\r\n\r\n\tlet newString = thisString.substring(0, 1).toLocaleUpperCase();\r\n\r\n\tif (thisString.length > 1) {\r\n\t\tnewString += thisString.substring(1);\r\n\t}\r\n\r\n\treturn newString;\r\n}\r\n\r\n/**\r\n * Converts the first character in a string to upper-case. Will not work for all languages (for example Dutch).\r\n *\r\n * @export\r\n * @param {string} thisString\r\n * @returns\r\n */\r\nexport function firstCharacterToLower(thisString: string) {\r\n\tif (!thisString) {\r\n\t\treturn '';\r\n\t}\r\n\r\n\tlet newString = thisString.substring(0, 1).toLocaleLowerCase();\r\n\r\n\tif (thisString.length > 1) {\r\n\t\tnewString += thisString.substring(1);\r\n\t}\r\n\r\n\treturn newString;\r\n}\r\n\r\n// https://github.com/uxitten/polyfill/blob/master/string.polyfill.js\r\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart\r\nexport function padStart(value, targetLength, padString) {\r\n\t// tslint:disable-next-line:no-bitwise\r\n\ttargetLength = targetLength >> 0; // truncate if number, or convert non-number to 0;\r\n\tpadString = String(typeof padString !== 'undefined' ? padString : ' ');\r\n\tif (value.length >= targetLength) {\r\n\t\treturn String(value);\r\n\t} else {\r\n\t\ttargetLength = targetLength - value.length;\r\n\t\tif (targetLength > padString.length) {\r\n\t\t\tpadString += padString.repeat(targetLength / padString.length); // append to original to ensure we are longer than needed\r\n\t\t}\r\n\t\treturn padString.slice(0, targetLength) + String(value);\r\n\t}\r\n}\r\n\r\n/**\r\n * Converts a string from \" Something Like This\" to \"something-like-this\"\r\n * @param value The string to convert\r\n */\r\nexport function toKebabCase(value: string) {\r\n\tif (!value || !value.trim()) {\r\n\t\treturn '';\r\n\t}\r\n\r\n\treturn value\r\n\t\t.trim()\r\n\t\t.replace(/[^a-zA-Z0-9]+/g, '-')\r\n\t\t.replace(/([a-z0-9])([A-Z])/g, '$1-$2')\r\n\t\t.replace(/([A-Z])([A-Z])(?=[a-z])/g, '$1-$2')\r\n\t\t.replace(/-$/, '')\r\n\t\t.toLocaleLowerCase();\r\n}\r\n\r\n/**\r\n * Converts a string from PascalCase, camelCase, snake_case, or space separated to camelCase. Beginning and trailing whitespace are trimmed.\r\n * @param value The string to convert\r\n */\r\nexport function toCamelCase(value: string) {\r\n\treturn value\r\n\t\t.replace(/(?:^\\w|[A-Z]|\\b\\w)/g, function (word, index) {\r\n\t\t\treturn index === 0 ? word.toLowerCase() : word.toUpperCase();\r\n\t\t})\r\n\t\t.replace(/(?:\\s+|[-_])/g, '');\r\n}\r\n\r\n/**\r\n * Removes html characters\r\n *\r\n * @export\r\n * @param {*} html\r\n * @returns\r\n */\r\nexport function stripHtml(html) {\r\n\tconst tmp = document.createElement('div');\r\n\ttmp.innerHTML = html;\r\n\treturn tmp.textContent || tmp.innerText || '';\r\n}\r\n\r\n/**\r\n * Cuts of text and adds ellipsis (...) after a certain number of characters\r\n * @param text The text to format\r\n * @param cutoff The number of characters to add the ellipsis after\r\n */\r\nexport function addEllipsis(text: string, cutoff: number = 20) {\r\n\tif (!text || text.length < cutoff) {\r\n\t\treturn text;\r\n\t}\r\n\r\n\treturn text.substring(0, cutoff) + '...';\r\n}\r\n\r\n/**\r\n * Trims a string value\r\n */\r\nexport function trimString(value: string) {\r\n\treturn value ? value.trim() : '';\r\n}\r\n","import { CancelToken } from 'axios';\r\nimport { Request as AutocompleteRequest, Response as AutocompleteResponse } from 'models/Autocomplete';\r\nimport { Request as CompareItemRequest, Response as CompareDataResponse } from 'models/CompareItems';\r\nimport { Request as SearchRequest, Response as SearchResponse } from 'models/Search';\r\nimport { HawkSearchConfig } from 'types/HawkSearchConfig';\r\nimport * as Constants from 'util/Constants';\r\nimport AxiosHelper from '../../../../services/AxiosHelper';\r\nimport { Request as RecommendationRequest, Response as RecommendationResponse } from '../models/Recommendation';\r\n\r\nclass HawkClient {\r\n\tprivate baseUrl: string;\r\n\tprivate searchUrl: string;\r\n\tprivate dashboardUrl: string;\r\n\tprivate autocompleteUrl: string;\r\n\tprivate compareItemsURL: string;\r\n\tprivate recommendationUrl: string;\r\n\tprivate recommendationWidgetUrl: string;\r\n\t// #region HCL\r\n\tprivate enableRemovingDashesFromSearchKeyword: boolean;\r\n\t// #endregion\r\n\r\n\tconstructor(config: HawkSearchConfig) {\r\n\t\tthis.baseUrl = config.apiUrl || Constants.defaultApiUrl;\r\n\t\tthis.dashboardUrl = config.dashboardUrl || Constants.defaultDashboardUrl;\r\n\t\tthis.searchUrl = config.searchUrl || Constants.defaultSearchUrl;\r\n\t\tthis.autocompleteUrl = config.autocompleteUrl || Constants.defaultAutocompleteUrl;\r\n\t\tthis.recommendationUrl = config.recommendationUrl || Constants.defaultRecommendationUrl;\r\n\t\tthis.recommendationWidgetUrl = config.recommendationWidgetUrl || Constants.recommendationWidgetUrl;\r\n\t\t/* #region Commerce */\r\n\t\tthis.compareItemsURL = config.compareItemsURL || Constants.defaultCompareItemsURL;\r\n\t\t/* #endregion */\r\n\t\t/* #region HCL */\r\n\t\tthis.enableRemovingDashesFromSearchKeyword =\r\n\t\t\tconfig.enableRemovingDashesFromSearchKeyword || Constants.enableRemovingDashesFromSearchKeyword;\r\n\t\t/* #endregion */\r\n\t}\r\n\r\n\t// #region HCL\r\n\tpublic async search(request: SearchRequest, cancellationToken?: CancelToken): Promise {\r\n\t\tconst result = await AxiosHelper.post(\r\n\t\t\t'/ajax/hawksearch/search',\r\n\t\t\t{ request },\r\n\t\t\t{ cancelToken: cancellationToken },\r\n\t\t);\r\n\r\n\t\treturn result.data;\r\n\t}\r\n\r\n\tpublic async autocomplete(\r\n\t\trequest: AutocompleteRequest,\r\n\t\tcancellationToken?: CancelToken,\r\n\t): Promise {\r\n\t\tconst result = await AxiosHelper.post(\r\n\t\t\t'/ajax/hawksearch/autocomplete',\r\n\t\t\t{ request },\r\n\t\t\t{ cancelToken: cancellationToken },\r\n\t\t);\r\n\r\n\t\treturn result.data;\r\n\t}\r\n\r\n\tpublic async getComparedItems(\r\n\t\trequest: CompareItemRequest,\r\n\t\tcancellationToken?: CancelToken,\r\n\t): Promise {\r\n\t\tconst result = await AxiosHelper.post(\r\n\t\t\t'/ajax/hawksearch/compare',\r\n\t\t\t{ request },\r\n\t\t\t{ cancelToken: cancellationToken },\r\n\t\t);\r\n\r\n\t\treturn result.data;\r\n\t}\r\n\r\n\tpublic async getRecommendationWidgetItems(\r\n\t\trequest: RecommendationRequest,\r\n\t\tcancellationToken?: CancelToken,\r\n\t): Promise {\r\n\t\tconst result = await AxiosHelper.post(\r\n\t\t\t'/ajax/hawksearch/recommendation',\r\n\t\t\t{ request },\r\n\t\t\t{ cancelToken: cancellationToken },\r\n\t\t);\r\n\r\n\t\treturn result.data;\r\n\t}\r\n\t// #endregion\r\n}\r\n\r\nexport default HawkClient;\r\n","import { ExternalLoginProvider } from 'features/login/ExternalLogins';\r\n\r\n/**\r\n * Extends Window with a property that will hold the client data\r\n *\r\n * @interface WindowWithClientData\r\n * @extends {Window}\r\n */\r\ninterface WindowWithServerData extends Window {\r\n\t__ROC_SERVER_DATA__?: Array<{\r\n\t\t[name: string]: string;\r\n\t}>;\r\n}\r\n\r\n/**\r\n * This type will hold all the keys that are used by ServerData\r\n */\r\ninterface ServerData {\r\n\tIsReCaptchaEnabled?: boolean;\r\n\tReCaptchaV3Key?: string;\r\n\tTimeZone?: string;\r\n\tUSE_EMAIL_AS_USERNAME?: boolean;\r\n\tRegistrationThankYouTitle?: string;\r\n\tRegistrationThankYouMessage?: string;\r\n\tForgotPasswordConfirmationTitle?: string;\r\n\tForgotPasswordConfirmationMessage?: string;\r\n\tPageTitleSuffix?: string;\r\n\tRequireConfirmEmail?: boolean;\r\n\tACCOUNT_URL_BASE?: string;\r\n\tACCOUNT_LOGIN_URL?: string;\r\n\tACCOUNT_LOGOUT_URL?: string;\r\n\tACCOUNT_REGISTER_URL?: string;\r\n\tACCOUNT_LOGIN_WITH_2FA_URL?: string;\r\n\tACCOUNT_FORGOT_PASSWORD_URL?: string;\r\n\tACCOUNT_LOGIN_WITH_RECOVERY_CODE_URL?: string;\r\n\tEXTERNAL_LOGIN_PROVIDERS?: ExternalLoginProvider[];\r\n\t// #region Commerce\r\n\tACCOUNT_ORGANIZATION_REVIEW_URL?: string;\r\n\tACCOUNT_ORGANIZATION_SELECTOR_URL?: string;\r\n\tGoogleMapsApiKey?: string; // used in Store Locator\r\n\tMinimumTimeBeforeRecentlyViewedProductsAreValidated?: number;\r\n\tQuickOrderItemMinumumSearchCharacters?: number;\r\n\tMaxAllowedQuickOrderItems?: number;\r\n\tMaxNumberForQuantityDropdown?: number;\r\n\tOrderDetailsUIComponent?: string;\r\n\tGuestCheckoutEnabled?: boolean;\r\n\t// #endregion\r\n}\r\n\r\n/**\r\n * Main object that will hold all the client data\r\n */\r\nexport const ServerData: ServerData = {};\r\n\r\n/**\r\n * Initializer function that will populate the main settings object\r\n */\r\nfunction initializeServerData() {\r\n\tconst windowWithServerData = window as WindowWithServerData;\r\n\r\n\tif (\r\n\t\twindowWithServerData &&\r\n\t\twindowWithServerData.__ROC_SERVER_DATA__ &&\r\n\t\tArray.isArray(windowWithServerData.__ROC_SERVER_DATA__)\r\n\t) {\r\n\t\tfor (const obj of windowWithServerData.__ROC_SERVER_DATA__) {\r\n\t\t\tfor (const key of Object.keys(obj)) {\r\n\t\t\t\tServerData[key] = obj[key];\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\ninitializeServerData();\r\n","import React from 'react';\r\nimport useDelayedDisplay from 'shared/hooks/useDelayedDisplay';\r\nimport classnames from 'classnames';\r\n\r\ntype SpinnerAlignment = 'left' | 'right' | 'none';\r\n\r\ninterface SpinnerProps {\r\n\tlight?: boolean;\r\n\twaitMs?: number;\r\n\talign?: SpinnerAlignment;\r\n\tblock?: boolean;\r\n\tparentCentered?: boolean;\r\n}\r\n\r\n/**\r\n * Reusable roc-spinner component with color, alignment and wait time props.\r\n *\r\n * @export\r\n * @param {SpinnerProps} { light = false, waitMs = 200, align = 'right', block }\r\n * @returns\r\n */\r\nexport default function Spinner({\r\n\tlight = false,\r\n\twaitMs = 200,\r\n\talign = 'right',\r\n\tblock,\r\n\tparentCentered = false,\r\n}: SpinnerProps) {\r\n\tconst display = useDelayedDisplay(waitMs);\r\n\r\n\tif (!display) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\tconst spinner = (\r\n\t\t\r\n\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t
\r\n\t\t
\r\n\t);\r\n\r\n\tif (parentCentered) {\r\n\t\treturn
{spinner}
;\r\n\t}\r\n\r\n\treturn spinner;\r\n}\r\n","import axios, { AxiosInstance, AxiosResponse, AxiosError } from 'axios';\r\nimport AccountUrls from 'shared/util/AccountUrls';\r\nimport { getCsrfToken } from './UserData';\r\n\r\n/**\r\n * Helper that creates an instance of Axios to be used throughout the client application\r\n * and adds a default X-Requested-With header to all requests.\r\n *\r\n */\r\nconst AxiosHelper: AxiosInstance = axios.create();\r\nAxiosHelper.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';\r\n\r\n// Add CSRF tokens to all commands that are not GET, HEAD, or OPTIONS\r\nAxiosHelper.interceptors.request.use(async (config) => {\r\n\tif (\r\n\t\tconfig.method?.toLowerCase() !== 'get' &&\r\n\t\tconfig.method?.toLowerCase() !== 'head' &&\r\n\t\tconfig.method?.toLowerCase() !== 'options'\r\n\t) {\r\n\t\tconst csrfToken = await getCsrfToken();\r\n\t\tconfig.headers = { RequestVerificationToken: csrfToken, ...config.headers };\r\n\t}\r\n\treturn config;\r\n});\r\n\r\nexport default AxiosHelper;\r\n\r\n// eslint-disable-next-line no-unused-vars\r\nexport const addUnauthorizedAccessInterceptor = (history) => {\r\n\t// this allows us to act when any request going through axios succeeds or fails.\r\n\tAxiosHelper.interceptors.response.use(\r\n\t\t(response: AxiosResponse) => {\r\n\t\t\treturn response;\r\n\t\t},\r\n\t\t(error: AxiosError) => {\r\n\t\t\tif (error.response && error.response.status === 401) {\r\n\t\t\t\twindow.location.replace(\r\n\t\t\t\t\t`${AccountUrls.Login}?ReturnUrl=${encodeURIComponent(window.location.pathname)}`,\r\n\t\t\t\t);\r\n\t\t\t}\r\n\r\n\t\t\treturn Promise.reject(error);\r\n\t\t},\r\n\t);\r\n};\r\n","import { ProductDetailSelection, ProductSelection } from 'features/commerce/product-details/types';\r\nimport { Order, OrderItem } from 'features/commerce/shopping-cart/types';\r\nimport addRocEventHandler from 'shared/util/events/rocEventUtils';\r\nimport { CommercePageType, TrackSaleItemArgs } from './tracking-commerce';\r\nimport HawkSearch from '../../hawksearch/tracking';\r\n\r\n/**\r\n * Helper function for converting order model to the list of items in format expected by Google Analytics\r\n * @param order\r\n */\r\nfunction convertOrderToHawkSearchItems(order: Order): Array {\r\n\t// helper function for resolving item's price\r\n\tconst resolveItemPrice = (item: OrderItem): number => {\r\n\t\tif (item.unitPrice) {\r\n\t\t\tif (item.unitPrice.salePrice) {\r\n\t\t\t\treturn item.unitPrice.salePrice.rawValue;\r\n\t\t\t}\r\n\r\n\t\t\tif (item.unitPrice.basePrice) {\r\n\t\t\t\treturn item.unitPrice.basePrice.rawValue;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn 0;\r\n\t};\r\n\r\n\treturn order.recipients.reduce(\r\n\t\t(items, recipient) => [\r\n\t\t\t...items,\r\n\t\t\t...recipient.items.map((item) => {\r\n\t\t\t\treturn {\r\n\t\t\t\t\tuniqueId: item.product.productGroupId ?? item.product.id,\r\n\t\t\t\t\titemPrice: resolveItemPrice(item),\r\n\t\t\t\t\tquantity: item.quantity,\r\n\t\t\t\t};\r\n\t\t\t}),\r\n\t\t],\r\n\t\t[],\r\n\t);\r\n}\r\n\r\n/**\r\n * Represents attributes and values used for adding in hawksearch context\r\n */\r\nexport interface HawksearchAttributes {\r\n\tname: string;\r\n\tvalue?: string;\r\n}\r\n\r\n/**\r\n * Helper function to add the associated group product Id of a simple product, if applicable.\r\n * @param uniqueId - the associated unique group product Id of a simple product, if applicable.\r\n */\r\nfunction addProductToContext(uniqueId: string) {\r\n\tHawkSearch.Context.add('unique_id', uniqueId.toString());\r\n}\r\n\r\n/**\r\n * Helper function to add multiple associated group product Ids of a simple product, if applicable.\r\n * @param uniqueId - the associated unique group product Id of a simple product, if applicable.\r\n */\r\nfunction addMultipleProductsToContext(uniqueId: string) {\r\n\tHawkSearch.Context.push('unique_id', uniqueId.toString());\r\n}\r\n\r\n/**\r\n * Helper function to add attribute value to hawk context\r\n * @param selections - The list of selectable attributes and their values for the product which are relevant for product recommendations.\r\n */\r\nfunction addProductAttributesToContext(hawkAttributes: HawksearchAttributes[]) {\r\n\t// add attribute to context if the tracking key is present\r\n\thawkAttributes?.map((attribute) => {\r\n\t\tif (attribute.value) {\r\n\t\t\tHawkSearch.Context.add(attribute.name, attribute.value);\r\n\t\t} else {\r\n\t\t\tHawkSearch.Context.remove(attribute.name);\r\n\t\t}\r\n\t});\r\n}\r\n\r\n/**\r\n * Helper function to add multiple attribute values to hawk context separated by ','\r\n * @param selections - The list of selectable attributes and their values for the product which are relevant for product recommendations.\r\n */\r\nfunction addMultipleProductAttributesToContext(hawkAttributes: HawksearchAttributes[]) {\r\n\t// add attribute to context if the tracking key is present\r\n\thawkAttributes?.map((attribute) => {\r\n\t\tif (attribute.value) {\r\n\t\t\tHawkSearch.Context.push(attribute.name, attribute.value);\r\n\t\t} else {\r\n\t\t\tHawkSearch.Context.remove(attribute.name);\r\n\t\t}\r\n\t});\r\n}\r\n\r\n/**\r\n * Converts roc product selections to hawk context attribute fields\r\n * @param selections - The list of selectable attributes and their values for the product which are relevant for product recommendations.\r\n */\r\nexport function selectionsToHawkAttributes(\r\n\tselections: ProductDetailSelection[] | undefined | null,\r\n): HawksearchAttributes[] {\r\n\tconst hawkSearchAttributes: HawksearchAttributes[] = selections?.length\r\n\t\t? selections.map((selection: ProductDetailSelection) => {\r\n\t\t\t\treturn {\r\n\t\t\t\t\tname: selection.field,\r\n\t\t\t\t\tvalue: selection.values?.find((s) => s.checked === true)?.label ?? undefined,\r\n\t\t\t\t};\r\n\t\t })\r\n\t\t: [];\r\n\r\n\treturn hawkSearchAttributes;\r\n}\r\n\r\n/**\r\n * Converts roc product selections to hawk context attribute fields\r\n */\r\nexport function convertProductSelectionToHawksearchAttributes(\r\n\tselections: ProductSelection[] | null | undefined,\r\n): HawksearchAttributes[] {\r\n\tconst hawkSearchAttributes: HawksearchAttributes[] = selections?.length\r\n\t\t? selections.map((selection: ProductSelection) => {\r\n\t\t\t\treturn {\r\n\t\t\t\t\tname: selection.field,\r\n\t\t\t\t\tvalue: selection.label.toString() ?? undefined,\r\n\t\t\t\t};\r\n\t\t })\r\n\t\t: [];\r\n\r\n\treturn hawkSearchAttributes;\r\n}\r\n\r\nexport default function setup() {\r\n\taddRocEventHandler('cart-page-viewed', () => {\r\n\t\tHawkSearch.Tracking.track('pageload', {\r\n\t\t\tpageType: CommercePageType.cart,\r\n\t\t\tuniqueId: '',\r\n\t\t});\r\n\t});\r\n\r\n\taddRocEventHandler('product-viewed', ({ productId, productGroupId, selections }) => {\r\n\t\tif (productGroupId != null) {\r\n\t\t\tconst hawkAttributes = selectionsToHawkAttributes(selections);\r\n\t\t\taddProductAttributesToContext(hawkAttributes);\r\n\t\t}\r\n\t\taddProductToContext(productGroupId ?? productId);\r\n\r\n\t\tHawkSearch.Tracking.track('pageload', {\r\n\t\t\tpageType: CommercePageType.item,\r\n\t\t\tuniqueId: productGroupId ?? productId,\r\n\t\t});\r\n\t});\r\n\r\n\taddRocEventHandler('product-rated', ({ productId, rating }) => {\r\n\t\tHawkSearch.Tracking.trackCommerce('rate', {\r\n\t\t\tuniqueId: productId,\r\n\t\t\tvalue: rating,\r\n\t\t});\r\n\t});\r\n\r\n\taddRocEventHandler('order-placed', ({ order }) => {\r\n\t\torder.recipients.map((recipient) => {\r\n\t\t\trecipient.items.map((item) => {\r\n\t\t\t\tif (item.product.productGroupId != null) {\r\n\t\t\t\t\tconst hawkAttributes = convertProductSelectionToHawksearchAttributes(item.selections);\r\n\t\t\t\t\taddMultipleProductAttributesToContext(hawkAttributes);\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t});\r\n\r\n\t\tHawkSearch.Tracking.trackCommerce('sale', {\r\n\t\t\torderNo: order.orderNo || order.orderCode,\r\n\t\t\tcurrency: order.snapshotCurrencyISO,\r\n\t\t\titemList: convertOrderToHawkSearchItems(order),\r\n\t\t\tsubTotal: order.subtotal.basePrice.rawValue,\r\n\t\t\ttax: order.tax?.basePrice.rawValue,\r\n\t\t\ttotal: order.total.basePrice.rawValue,\r\n\t\t});\r\n\r\n\t\tHawkSearch.Tracking.track('pageload', { pageType: CommercePageType.order, uniqueId: '' });\r\n\t});\r\n\r\n\taddRocEventHandler('added-to-cart', ({ items }) => {\r\n\t\titems.map((item) => {\r\n\t\t\tif (item.productGroupId) {\r\n\t\t\t\tconst hawkAttributes = convertProductSelectionToHawksearchAttributes(item.selections);\r\n\t\t\t\taddProductAttributesToContext(hawkAttributes);\r\n\t\t\t}\r\n\t\t\taddProductToContext(item.productGroupId ?? item.id);\r\n\t\t});\r\n\r\n\t\tHawkSearch.Tracking.trackCommerce('add2cartmultiple', {\r\n\t\t\titemsList: items.map((item) => {\r\n\t\t\t\treturn {\r\n\t\t\t\t\tcurrency: item.currency,\r\n\t\t\t\t\tprice: item.price,\r\n\t\t\t\t\tquantity: item.adjustedQuantity,\r\n\t\t\t\t\tuniqueId: item.productGroupId ?? item.id,\r\n\t\t\t\t};\r\n\t\t\t}),\r\n\t\t});\r\n\t});\r\n\r\n\taddRocEventHandler('added-to-cart-multiple', ({ items }) => {\r\n\t\titems.map((item) => {\r\n\t\t\tif (item.productGroupId) {\r\n\t\t\t\tconst hawkAttributes = convertProductSelectionToHawksearchAttributes(item.selections);\r\n\t\t\t\taddMultipleProductAttributesToContext(hawkAttributes);\r\n\t\t\t}\r\n\t\t\taddMultipleProductsToContext(item.productGroupId ?? item.id);\r\n\t\t});\r\n\r\n\t\tHawkSearch.Tracking.trackCommerce('add2cartmultiple', {\r\n\t\t\titemsList: items.map((item) => {\r\n\t\t\t\treturn {\r\n\t\t\t\t\tcurrency: item.currency,\r\n\t\t\t\t\tprice: item.price,\r\n\t\t\t\t\tquantity: item.adjustedQuantity,\r\n\t\t\t\t\tuniqueId: item.productGroupId ?? item.id,\r\n\t\t\t\t};\r\n\t\t\t}),\r\n\t\t});\r\n\t});\r\n\r\n\taddRocEventHandler('product-clicked', ({ productId, productGroupId, url }) => {\r\n\t\tif (!window.HawkSearchTrackingId) {\r\n\t\t\t// do not report product clicks unless there is tracking id from hawk\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tHawkSearch.Tracking.track('click', {\r\n\t\t\tuniqueId: productGroupId ?? productId,\r\n\t\t\turl: url,\r\n\t\t\ttrackingId: window.HawkSearchTrackingId,\r\n\t\t});\r\n\t});\r\n\r\n\taddRocEventHandler('product-selection-updated', ({ product }) => {\r\n\t\tconst hawkAttributes = selectionsToHawkAttributes(product.productDetails?.selections);\r\n\t\taddProductAttributesToContext(hawkAttributes);\r\n\t\taddProductToContext(product.productDetails?.summary?.productGroupId ?? product.productId);\r\n\t});\r\n}\r\n","import React from 'react';\r\nimport classnames from 'classnames';\r\nimport { Localizer } from 'services/Localizer';\r\nimport { AxiosError } from 'axios';\r\nimport XSVG from 'shared/components/svg/XSVG';\r\n\r\ntype Theme = 'danger' | 'warning' | 'info' | 'success';\r\n\r\nexport interface ErrorAlertProps {\r\n\t/**\r\n\t * The title of the error message such as \"Uh Oh!\" or \"An Unexpected Error has Occurred!\"\r\n\t */\r\n\ttitle: string;\r\n\r\n\t/**\r\n\t * The error message to display if an error object doesn't have a more appropriate message.\r\n\t */\r\n\tmessage: React.ReactNode | string;\r\n\r\n\tchildren?: any;\r\n\r\n\ttheme?: Theme;\r\n\r\n\tisTitleOnOwnRow?: boolean;\r\n\r\n\t/** The error responsible for this message. */\r\n\terror: AxiosError | Error | null;\r\n\r\n\t/**\r\n\t * Method from parent that handles collapse state.\r\n\t */\r\n\tonCollapse?: (collased: boolean) => void;\r\n\r\n\t/**\r\n\t * Controlled collapse state from parent.\r\n\t */\r\n\tisCollapsed?: boolean;\r\n}\r\n\r\n/**\r\n * Reusable Error Alert Component.\r\n */\r\nexport default function InlineAlert(props: ErrorAlertProps) {\r\n\tconst {\r\n\t\ttitle = InlineAlert.defaultProps.title,\r\n\t\tchildren,\r\n\t\ttheme = 'danger',\r\n\t\tisTitleOnOwnRow = false,\r\n\t\terror = InlineAlert.defaultProps.error,\r\n\t\tisCollapsed = false,\r\n\t\tonCollapse,\r\n\t} = props;\r\n\r\n\tlet { message = InlineAlert.defaultProps.message } = props;\r\n\r\n\tconst axiosError = error as AxiosError | null;\r\n\tif (axiosError?.isAxiosError && axiosError != null && axiosError.response == null && axiosError.request != null) {\r\n\t\tmessage = Localizer('ErrorMessageNetwork');\r\n\t}\r\n\r\n\tif (axiosError?.isAxiosError && (axiosError?.response?.status === 401 || axiosError?.response?.status === 403)) {\r\n\t\tmessage = Localizer('ErrorMessageForbidden');\r\n\t}\r\n\r\n\tif (axiosError?.response?.data?.message) {\r\n\t\tmessage = axiosError.response.data.message;\r\n\t}\r\n\r\n\tif (isCollapsed) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\treturn (\r\n\t\t\r\n\t\t\t{onCollapse ? (\r\n\t\t\t\t\r\n\t\t\t) : null}\r\n\r\n\t\t\t{title ? (\r\n\t\t\t\t\r\n\t\t\t\t\t{title}\r\n\t\t\t\t\r\n\t\t\t) : null}\r\n\r\n\t\t\t{message ? {message} : null}\r\n\r\n\t\t\t{children ? <> {children} : null}\r\n\t\t
\r\n\t);\r\n}\r\n\r\n/**\r\n * Error Alert Default Props\r\n */\r\nInlineAlert.defaultProps = {\r\n\ttitle: Localizer('ErrorMessageGenericTitle'),\r\n\tmessage: Localizer('UnexpectedErrorOccurred'),\r\n\terror: null,\r\n};\r\n","import { useEffect } from 'react';\r\nimport 'shared/polyfills/customEvent';\r\nimport { RocEventType, ExtractEventParameters, RocEvent } from 'shared/events';\r\nimport addRocEventHandler from 'shared/util/events/rocEventUtils';\r\n\r\n/**\r\n * Helper function for dispatching ROC events.\r\n *\r\n * @param eventType The event type for the dispatcher\r\n */\r\nexport function dispatchRocEvent(eventType: T, data: ExtractEventParameters) {\r\n\tconst event = new CustomEvent(eventType, {\r\n\t\tdetail: data,\r\n\t});\r\n\tdocument.dispatchEvent(event);\r\n}\r\n\r\n/**\r\n * Reusable hook for handling ROC events\r\n *\r\n * @param eventType The type of event to handle\r\n * @param eventHandler The event handler\r\n * @param deps List of dependencies\r\n */\r\nexport default function useRocEventHandler(\r\n\teventType: T,\r\n\teventHandler: (data: ExtractEventParameters) => void,\r\n\tdeps?: any[],\r\n) {\r\n\tuseEffect(() => {\r\n\t\tconst removeHandlerCallback = addRocEventHandler(eventType, eventHandler);\r\n\r\n\t\treturn () => {\r\n\t\t\tremoveHandlerCallback();\r\n\t\t};\r\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\r\n\t}, deps);\r\n}\r\n","import React from 'react';\r\nimport { SVGProps } from './SVGProps';\r\nimport classnames from 'classnames';\r\n\r\n/**\r\n * X SVG\r\n *\r\n * @returns\r\n */\r\nfunction XSVG({ className, ...rest }: SVGProps) {\r\n\treturn (\r\n\t\t\r\n\t\t\t\r\n\t\t\r\n\t);\r\n}\r\n\r\nexport default XSVG;\r\n","import AxiosHelper from 'services/AxiosHelper';\r\nimport { AxiosResponse } from 'axios';\r\n\r\nexport interface UserSummary {\r\n\tisSignedIn: boolean;\r\n\tuserName: string | null;\r\n\tfirstName: string | null;\r\n\tlastName: string | null;\r\n\temail: string | null;\r\n\tphoneNumber: string | null;\r\n\ttwoFactorEnabled: boolean;\r\n\thasRecoveryCodes: boolean;\r\n\tisMachineRemembered: boolean;\r\n\tannouncements: UserAnnouncement[];\r\n\tisExternalLoginUser: boolean;\r\n\t// #region HCL\r\n\tversaPayEnabled: boolean;\r\n\tversaPayRedirectUrl: string | null;\r\n\tazureUserId: string | null;\r\n\t// #endregion\r\n}\r\n\r\n/** Represents the details about an admin impersonation session of the logged in user. */\r\nexport interface Impersonation {\r\n\t/** The id of the admin impersonating the front end user. */\r\n\timpersonatorId: string;\r\n\r\n\t/** The name of the admin impersonating the front end user. */\r\n\timpersonatorName: string;\r\n\r\n\t/** The id of the active user impersonation session. */\r\n\tsessionId: string;\r\n}\r\n\r\nexport interface UserData {\r\n\t/**\r\n\t * Summary of user-specific details\r\n\t */\r\n\tsummary?: UserSummary;\r\n\r\n\t/**\r\n\t * CSRF validation token generated by the server\r\n\t */\r\n\trequestToken?: string;\r\n\r\n\t/**\r\n\t * The information on an impersonation session if one is active.\r\n\t * If an impersonation session isn't active this field will be undefined.\r\n\t */\r\n\timpersonation?: Impersonation;\r\n}\r\n\r\nexport interface UserAnnouncement {\r\n\t/** The id used as the primary key for the announcement in the database */\r\n\tid: string;\r\n\r\n\t/** An announcement to be displayed to the user */\r\n\tmessage: string;\r\n\r\n\t/** A list of pages where the announcement will be displayed. This will be an empty array if it is to be displayed on all pages. */\r\n\tpages: string[];\r\n}\r\n\r\nlet userDataPromise: Promise> | null = null;\r\n\r\n/**\r\n * Returns details related to the current user. By default, this is primarily their first/last name\r\n * and whether they are logged in or not. This can customized to include more details if necessary.\r\n */\r\nexport const getUserData = () => {\r\n\tif (userDataPromise === null) {\r\n\t\tuserDataPromise = AxiosHelper.get('/ajax/user');\r\n\t}\r\n\r\n\treturn userDataPromise;\r\n};\r\n\r\n/**\r\n * Returns non-cached details related to the current user. By default, this is primarily their first/last name\r\n * and whether they are logged in or not. This can customized to include more details if necessary.\r\n */\r\nexport const getUserDataNoCache = () => {\r\n\treturn AxiosHelper.get('/ajax/user');\r\n};\r\n\r\n/**\r\n * Returns a promise that will contain the CSRF token generated on the server to be used to validate\r\n * forms being posted via AJAX.\r\n */\r\nexport async function getCsrfToken() {\r\n\ttry {\r\n\t\tconst userData = await getUserData();\r\n\t\treturn userData.data.requestToken;\r\n\t} catch (error) {\r\n\t\tconsole.warn('Unable to load CSRF token.');\r\n\t\treturn '';\r\n\t}\r\n}\r\n\r\n// #region Commerce\r\nimport { CartSummary } from './UserData.Commerce';\r\nimport { LocationDto } from 'features/commerce/store-locator/types';\r\nimport { OrganizationInvite, OrganizationShipTo } from 'shared-client/types/commerce/organization';\r\nimport { AutoSuggestOption } from '../../../Roc.SharedClientApp/types/fields';\r\n\r\n// Commerce extensions to the UserData interface\r\nexport interface UserData {\r\n\t// #region HCL - allows null\r\n\tcartSummary?: CartSummary | null;\r\n\t// #endregion\r\n\r\n\t/***\r\n\t * The customer's default store location or null if not set\r\n\t */\r\n\tdefaultStoreLocation?: LocationDto | null;\r\n\r\n\t/**\r\n\t * If store is enabled for this site\r\n\t */\r\n\tenableStoreLocation?: boolean;\r\n}\r\n\r\n/***\r\n * Organization data and permissions\r\n */\r\nexport interface Organization {\r\n\tid: string;\r\n\tpurchaseOrderNumberRequired: boolean;\r\n\tcreditCardAllowed: boolean;\r\n\tgiftCardAllowed: boolean;\r\n\torganizationName: string;\r\n\tcorpAccountAllowed: boolean;\r\n}\r\n\r\n/***\r\n * Organization dto data\r\n */\r\nexport interface OrganizationDto extends AutoSuggestOption {}\r\n\r\n/***\r\n * User's organization and permissions data\r\n */\r\nexport interface UserSummary {\r\n\t/***\r\n\t * User's current default organization\r\n\t */\r\n\torganization: Organization | null;\r\n\r\n\t/***\r\n\t * The list of organizations the user is part of\r\n\t */\r\n\tuserOrganizations?: OrganizationDto[] | null;\r\n\r\n\t/***\r\n\t * The selected organization ship to\r\n\t */\r\n\tselectedShipTo: OrganizationShipTo | null;\r\n\r\n\t/***\r\n\t * Defines if the user has multiple shiptos to select from\r\n\t */\r\n\thasMultipleShipTos: boolean | null;\r\n\r\n\t/***\r\n\t * Defines if the user has saved payment methods\r\n\t */\r\n\thasSavedPaymentMethods: boolean | null;\r\n\r\n\t/***\r\n\t * The list of user permissions\r\n\t */\r\n\tpermissions?: UserPermissions;\r\n\r\n\t/***\r\n\t * The list of organizations the user is invited to join\r\n\t */\r\n\torganizationInvites?: OrganizationInvite[];\r\n\r\n\t/***\r\n\t * The user organization removal notification\r\n\t * Used to notify the user if he is no more part of his default organization\r\n\t */\r\n\tuserOrganizationRemovalNotification?: string;\r\n}\r\n\r\n/***\r\n * User's permissions\r\n */\r\nexport interface UserPermissions {\r\n\t/***\r\n\t * Defines if the current user can see organization users\r\n\t */\r\n\tcanSeeOrganizationUsers?: boolean;\r\n\r\n\t/***\r\n\t * Defines if the current user can assign roles to organization users\r\n\t */\r\n\tcanAssignRolesToOrganizationUsers?: boolean;\r\n\r\n\t/***\r\n\t * Defines if the current user can remove users from an organization\r\n\t */\r\n\tremoveUserFromOrganization?: boolean;\r\n\r\n\t/***\r\n\t * Defines if the current user can create organization users\r\n\t */\r\n\tcreateOrganizationUser?: boolean;\r\n\r\n\t/***\r\n\t * Defines if the current user can enable/disable ShipTos for organization users\r\n\t */\r\n\tmanageShipTosAssociation?: boolean;\r\n\r\n\t/***\r\n\t * Defines if the current user can see status of the organization users\r\n\t */\r\n\tcanSeePendingOrganizationUsers?: boolean;\r\n}\r\n// #endregion\r\n","import React from 'react';\r\nimport InlineAlert from 'shared/edit/InlineAlert';\r\n\r\n// eslint-disable-next-line\r\n// tslint:disable-next-line\r\nexport interface ErrorBoundaryRenderProps extends ErrorBoundaryState {}\r\n\r\nexport interface ErrorBoundaryProps {\r\n\tchildren: React.ReactNode;\r\n\trenderError?: (renderProps: ErrorBoundaryRenderProps) => React.ReactNode;\r\n}\r\n\r\nexport interface ErrorBoundaryState {\r\n\terror?: Error;\r\n}\r\n\r\n/**\r\n * Default Error Boundary component for frontend components, so that in case a JS error occurs, we show\r\n * something instead of nothing.\r\n */\r\nexport default class ErrorBoundary extends React.Component {\r\n\tpublic static defaultProps = {\r\n\t\trenderError: (renderProps: ErrorBoundaryRenderProps) => ,\r\n\t};\r\n\r\n\tpublic state: ErrorBoundaryState = {};\r\n\r\n\tpublic componentDidCatch(error: Error) {\r\n\t\tif (error.name === 'ChunkLoadError') {\r\n\t\t\tconst lastRefreshedTimestamp = new Date(\r\n\t\t\t\tparseInt(window.localStorage.getItem('force-refresh-timestamp') || '0'),\r\n\t\t\t);\r\n\t\t\tconst pageAlreadyRefreshedLessThan30SecondsAgo =\r\n\t\t\t\tnew Date(lastRefreshedTimestamp.getTime() + 30 * 1000) > new Date();\r\n\r\n\t\t\tif (!pageAlreadyRefreshedLessThan30SecondsAgo) {\r\n\t\t\t\t// Assuming that the user is not on the latest version of the application. Refresh the page immediately.\r\n\t\t\t\twindow.localStorage.setItem('force-refresh-timestamp', new Date().getTime().toString());\r\n\t\t\t\treturn window.location.reload();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.setState({\r\n\t\t\terror,\r\n\t\t});\r\n\t}\r\n\r\n\tpublic render() {\r\n\t\tif (this.state.error) {\r\n\t\t\treturn this.props.renderError!(this.state);\r\n\t\t}\r\n\r\n\t\treturn this.props.children;\r\n\t}\r\n}\r\n","import { ServerData } from 'services/ServerData';\r\n\r\nexport default {\r\n\tBaseUrl: ServerData.ACCOUNT_URL_BASE ?? '/my-account',\r\n\tLogin: ServerData.ACCOUNT_LOGIN_URL ?? '/my-account/login',\r\n\tLogin2fa: ServerData.ACCOUNT_LOGIN_WITH_2FA_URL ?? '/my-account/login-with-2fa',\r\n\tRegister: ServerData.ACCOUNT_REGISTER_URL ?? '/my-account/register',\r\n\tForgotPassword: ServerData.ACCOUNT_FORGOT_PASSWORD_URL ?? '/my-account/forgot-password',\r\n\tLoginWithRecoveryCode: ServerData.ACCOUNT_LOGIN_WITH_RECOVERY_CODE_URL ?? '/my-account/login-with-recovery-code',\r\n\tLogout: ServerData.ACCOUNT_LOGOUT_URL ?? '/my-account/logout',\r\n\t// #region Commerce\r\n\tOrganizationReview: ServerData.ACCOUNT_ORGANIZATION_REVIEW_URL ?? '/my-account/organization-review',\r\n\tOrganizationSelector: ServerData.ACCOUNT_ORGANIZATION_SELECTOR_URL ?? '/my-account/organization-selector',\r\n\t// #endregion\r\n\t// #region HCL - hardcoded same way as external login is\r\n\tExternalLogout: '/my-account/external-logout',\r\n\t// #endregion\r\n};\r\n","import { AxiosError } from 'axios';\r\nimport RocHawkConfig from 'features/search/RocHawkConfig';\r\nimport AxiosHelper from 'services/AxiosHelper';\r\nimport { getCookie, setCookie } from 'shared/components/hawksearch/helpers/Cookies';\r\nimport { ExtractEventParameters } from 'shared/events';\r\n//#region Commerce\r\nimport { CommercePageType, CommerceSuggestType, trackCommerce } from '../commerce/hawksearch/tracking-commerce';\r\n//#endregion\r\n\r\nexport interface HawkSearch {\r\n\tClientGuid: string;\r\n\tContext: ContextDictionary;\r\n\tCustomContext: ContextDictionary;\r\n\tTrackingUrl: string | null;\r\n\tinitCustomEvents?: () => void;\r\n}\r\n\r\ndeclare global {\r\n\tinterface Window {\r\n\t\tHawkSearch: HawkSearch;\r\n\t}\r\n}\r\n\r\nexport enum EventTrackingType {\r\n\tpageLoad = 1,\r\n\tsearch = 2,\r\n\tclick = 3,\r\n\tbannerClick = 7,\r\n\tbannerImpression = 8,\r\n\trecommendationClick = 10,\r\n\tautoCompleteClick = 11,\r\n}\r\n\r\n/**\r\n * The page type\r\n */\r\nexport enum PageType {\r\n\t/**\r\n\t * Landing Page\r\n\t */\r\n\tlanding = 2,\r\n\t/**\r\n\t * All other Page Types\r\n\t */\r\n\tcustom = 5,\r\n}\r\n\r\nexport enum SuggestType {\r\n\tPopularSearches = 1,\r\n\tTopContentMatches = 4,\r\n}\r\n\r\nexport enum SearchType {\r\n\tInitial = 1,\r\n\tRefinement = 2,\r\n}\r\n\r\ntype HawkEvents =\r\n\t| ({ name: 'pageload' } & TrackPageLoadArgs)\r\n\t| ({ name: 'searchtracking' } & TrackSearchTrackingArgs)\r\n\t| ({ name: 'click' } & TrackClickArgs)\r\n\t| ({ name: 'bannerclick' } & TrackBannerClickArgs)\r\n\t| ({ name: 'bannerimpression' } & TrackBannerImpressionArgs)\r\n\t| ({ name: 'autocompleteclick' } & TrackAutoCompleteClickArgs)\r\n\t| ({ name: 'recommendationclick' } & TrackRecommendationClickArgs);\r\n\r\nexport type HawkEventType = HawkEvents['name'];\r\n\r\nfunction track(eventName: T, args: ExtractEventParameters) {\r\n\tswitch (eventName.toLocaleLowerCase()) {\r\n\t\tcase 'pageload':\r\n\t\t\t//HawkSearch.Context.add(\"uniqueid\", \"123456789\");\r\n\t\t\t//HawkSearch.Tracking.track('pageload',{pageType: \"item\"});\r\n\t\t\treturn trackPageLoad((args as unknown) as TrackPageLoadArgs);\r\n\t\tcase 'searchtracking':\r\n\t\t\t//HawkSearch.Tracking.track(\"searchtracking\", {trackingId:\"a9bd6e50-e434-45b9-9f66-489eca07ad0a\", typeId: HawkSearch.Tracking.SearchType.Initial});\r\n\t\t\t//HawkSearch.Tracking.track(\"searchtracking\", {trackingId:\"a9bd6e50-e434-45b9-9f66-489eca07ad0a\", typeId: HawkSearch.Tracking.SearchType.Refinement});\r\n\t\t\treturn trackSearchTracking((args as unknown) as TrackSearchTrackingArgs);\r\n\t\tcase 'click':\r\n\t\t\t//HawkSearch.Tracking.track('click',{event: e, uniqueId: \"33333\", trackingId: \"75a0801a-a93c-4bcb-81f1-f4b011f616e3\"});\r\n\t\t\treturn trackClick((args as unknown) as TrackClickArgs);\r\n\t\tcase 'bannerclick':\r\n\t\t\t//HawkSearch.Tracking.track('bannerclick',{bannerId: 1, campaignId: 2, trackingId:\"2d652a1e-2e05-4414-9d76-51979109f724\"});\r\n\t\t\treturn trackBannerClick((args as unknown) as TrackBannerClickArgs);\r\n\t\tcase 'bannerimpression':\r\n\t\t\t//HawkSearch.Tracking.track('bannerimpression',{bannerId: \"2\", campaignId: \"2\", trackingId:\"2d652a1e-2e05-4414-9d76-51979109f724\"});\r\n\t\t\treturn trackBannerImpression((args as unknown) as TrackBannerImpressionArgs);\r\n\t\tcase 'autocompleteclick':\r\n\t\t\t//HawkSearch.Tracking.track('autocompleteclick',{keyword: \"test\", suggestType: HawkSearch.Tracking.SuggestType.PopularSearches, name:\"tester\", url:\"/test\"});\r\n\t\t\treturn trackAutoCompleteClick((args as unknown) as TrackAutoCompleteClickArgs);\r\n\t\tcase 'recommendationclick':\r\n\t\t\t//HawkSearch.Tracking.track('recommendationclick',{uniqueId: \"223222\", itemIndex: \"222\", widgetGuid:\"2d652a1e-2e05-4414-9d76-51979109f724\", requestId:\"2d652a1e-2e05-4414-9d76-51979109f724\"});\r\n\t\t\treturn trackRecommendationClick((args as unknown) as TrackRecommendationClickArgs);\r\n\t}\r\n}\r\n\r\nfunction getVisitorExpiry() {\r\n\tconst d = new Date();\r\n\t// 1 year\r\n\td.setTime(d.getTime() + 360 * 24 * 60 * 60 * 1000);\r\n\treturn d.toUTCString();\r\n}\r\n\r\nfunction getVisitExpiry() {\r\n\tconst d = new Date();\r\n\t// 4 hours\r\n\td.setTime(d.getTime() + 4 * 60 * 60 * 1000);\r\n\treturn d.toUTCString();\r\n}\r\n\r\nfunction createGuid() {\r\n\tconst s: string[] = [];\r\n\tconst hexDigits = '0123456789abcdef';\r\n\tfor (let i = 0; i < 36; i++) {\r\n\t\ts[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);\r\n\t}\r\n\ts[14] = '4'; // bits 12-15 of the time_hi_and_version field to 0010\r\n\ts[19] = hexDigits.substr(((s[19] as any) & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01\r\n\ts[8] = s[13] = s[18] = s[23] = '-';\r\n\r\n\treturn s.join('');\r\n}\r\n\r\ntype TrackPageLoadArgs = {\r\n\t/**\r\n\t * The page type\r\n\t */\r\n\tpageType:\r\n\t\t| PageType\r\n\t\t// #region Commerce\r\n\t\t| CommercePageType;\r\n\t// #endregion\r\n\r\n\t/**\r\n\t * Unique identifier of item that was clicked\r\n\t */\r\n\tuniqueId?: string;\r\n};\r\n\r\nfunction trackPageLoad({ pageType, uniqueId }: TrackPageLoadArgs) {\r\n\tconst { clientHeight, clientWidth } = document.documentElement;\r\n\r\n\tconst payload = {\r\n\t\tEventType: EventTrackingType.pageLoad,\r\n\t\tEventData: preparePayload({\r\n\t\t\tPageTypeId: pageType,\r\n\t\t\tRequestPath: window.location.pathname,\r\n\t\t\tQs: window.location.search,\r\n\t\t\tViewportHeight: clientHeight,\r\n\t\t\tViewportWidth: clientWidth,\r\n\t\t\tUniqueId: uniqueId,\r\n\t\t}),\r\n\t};\r\n\r\n\tmakeRequest(payload);\r\n}\r\n\r\ntype TrackSearchTrackingArgs = {\r\n\t/**\r\n\t * The ‘TrackingId’ object that is passed in this function is returned in the Hawksearch response\r\n\t */\r\n\ttrackingId: string;\r\n\t/**\r\n\t * The type of search that is performed\r\n\t */\r\n\ttypeId: SearchType;\r\n};\r\n\r\nfunction trackSearchTracking({ trackingId, typeId }: TrackSearchTrackingArgs) {\r\n\tif (typeId == SearchType.Initial) {\r\n\t\tsetCookie('hawk_query_id', createGuid());\r\n\t}\r\n\r\n\tconst queryId = getCookie('hawk_query_id');\r\n\tconst { clientHeight, clientWidth } = document.documentElement;\r\n\tconst payload = {\r\n\t\tEventType: EventTrackingType.search,\r\n\t\tEventData: preparePayload({\r\n\t\t\tQueryId: queryId,\r\n\t\t\tTrackingId: trackingId,\r\n\t\t\tTypeId: typeId,\r\n\t\t\tViewportHeight: clientHeight,\r\n\t\t\tViewportWidth: clientWidth,\r\n\t\t}),\r\n\t};\r\n\r\n\tmakeRequest(payload);\r\n}\r\n\r\ntype TrackClickArgs = {\r\n\t/**\r\n\t * Unique identifier of item that was clicked\r\n\t */\r\n\tuniqueId: string;\r\n\t/**\r\n\t * This is the TrackingId that was passed back in the search response\r\n\t */\r\n\ttrackingId: string;\r\n\t/**\r\n\t * Target URL that clicked element points to\r\n\t */\r\n\turl: string;\r\n};\r\n\r\nfunction trackClick({ uniqueId, trackingId, url }: TrackClickArgs) {\r\n\tconst { clientHeight, clientWidth } = document.documentElement;\r\n\r\n\tconst payload = {\r\n\t\tEventType: EventTrackingType.click,\r\n\t\tEventData: preparePayload({\r\n\t\t\tUrl: url,\r\n\t\t\tQs: window.location.search,\r\n\t\t\tRequestPath: window.location.pathname,\r\n\t\t\tTrackingId: trackingId,\r\n\t\t\tUniqueId: uniqueId,\r\n\t\t\tViewportHeight: clientHeight,\r\n\t\t\tViewportWidth: clientWidth,\r\n\t\t}),\r\n\t};\r\n\r\n\tmakeRequest(payload);\r\n}\r\n\r\ntype TrackBannerClickArgs = {\r\n\t/**\r\n\t * The identifier of corresponding banner\r\n\t */\r\n\tbannerId: string;\r\n\t/**\r\n\t * The identifier of corresponding campaign (optional)\r\n\t */\r\n\tcampaignId: string;\r\n\t/**\r\n\t * The ‘TrackingId’ object that is passed in this function is returned in the Hawksearch response\r\n\t */\r\n\ttrackingId: string;\r\n};\r\n\r\nfunction trackBannerClick({ bannerId, trackingId, campaignId }: TrackBannerClickArgs) {\r\n\tconst payload = {\r\n\t\tEventType: EventTrackingType.bannerClick,\r\n\t\tEventData: preparePayload({\r\n\t\t\tCampaignId: campaignId,\r\n\t\t\tBannerId: bannerId,\r\n\t\t\tTrackingId: trackingId,\r\n\t\t}),\r\n\t};\r\n\r\n\tmakeRequest(payload);\r\n}\r\n\r\ntype TrackBannerImpressionArgs = TrackBannerClickArgs;\r\n\r\nfunction trackBannerImpression({ bannerId, campaignId, trackingId }: TrackBannerImpressionArgs) {\r\n\tconst payload = {\r\n\t\tEventType: EventTrackingType.bannerImpression,\r\n\t\tEventData: preparePayload({\r\n\t\t\tCampaignId: campaignId,\r\n\t\t\tBannerId: bannerId,\r\n\t\t\tTrackingId: trackingId,\r\n\t\t}),\r\n\t};\r\n\tmakeRequest(payload);\r\n}\r\n\r\ntype TrackAutoCompleteClickArgs = {\r\n\t/**\r\n\t * Selected keyword used as a autocomplete query\r\n\t */\r\n\tkeyword: string;\r\n\t/**\r\n\t * The type of autocomplete results type\r\n\t */\r\n\tsuggestType?: SuggestType | CommerceSuggestType;\r\n\t/**\r\n\t * Text value associated with the autocomplete item clicked\r\n\t */\r\n\titemName: string;\r\n\t/**\r\n\t * The target URL of clicked autocomplete item\r\n\t */\r\n\turl: string;\r\n};\r\n\r\nfunction trackAutoCompleteClick({ keyword, suggestType, itemName, url }: TrackAutoCompleteClickArgs) {\r\n\tconst payload = {\r\n\t\tEventType: EventTrackingType.autoCompleteClick,\r\n\t\tEventData: preparePayload({\r\n\t\t\tKeyword: keyword,\r\n\t\t\tName: itemName,\r\n\t\t\tSuggestType: suggestType,\r\n\t\t\tUrl: url,\r\n\t\t}),\r\n\t};\r\n\r\n\tmakeRequest(payload);\r\n}\r\n\r\ntype TrackRecommendationClickArgs = {\r\n\t/**\r\n\t * The unique identifier of the recommendation widget that displayed clicked item. This should correspond to the widget GUID generated for each widget individually in Hawksearch dashboard\r\n\t */\r\n\twidgetGuid: string;\r\n\t/**\r\n\t * Represents the unique identifier of a product. This should correspond to the value of the field set up as the primary key in the fields section of Hawksearch dashboard.\r\n\t */\r\n\tuniqueId: string;\r\n\t/**\r\n\t * The number of the clicked recommendation item on the displayed widget.\r\n\t */\r\n\titemIndex: number;\r\n\t/**\r\n\t * The ‘RequestId’ object that is passed in this function is returned in the recommendation widget response\r\n\t */\r\n\trequestId: string;\r\n};\r\n\r\nfunction trackRecommendationClick({ widgetGuid, uniqueId, itemIndex, requestId }: TrackRecommendationClickArgs) {\r\n\tconst payload = {\r\n\t\tEventType: EventTrackingType.recommendationClick,\r\n\t\tEventData: preparePayload({\r\n\t\t\tItemIndex: itemIndex,\r\n\t\t\tRequestId: requestId,\r\n\t\t\tUniqueId: uniqueId,\r\n\t\t\tWidgetGuid: widgetGuid,\r\n\t\t}),\r\n\t};\r\n\r\n\tmakeRequest(payload);\r\n}\r\n\r\n// #region HCL\r\nfunction safeBtoa(input: string): string {\r\n\t// Encode the string into UTF-8 and then to base64\r\n\tconst utf8Bytes = new TextEncoder().encode(input);\r\n\treturn btoa(String.fromCharCode(...utf8Bytes));\r\n}\r\n// #endregion\r\n\r\nexport function preparePayload(payload: any) {\r\n\t// #region HCL\r\n\treturn safeBtoa(JSON.stringify(payload));\r\n\t// #endregion\r\n}\r\n\r\nexport function makeRequest(data) {\r\n\tif (!HawkSearch.TrackingUrl) {\r\n\t\tconsole.warn(\r\n\t\t\t\"Unable to send tracking event to HawkSearch because site's configuration is missing tracking URL.\",\r\n\t\t);\r\n\t\treturn;\r\n\t}\r\n\r\n\tlet visitId = getCookie('hawk_visit_id');\r\n\tlet visitorId = getCookie('hawk_visitor_id');\r\n\tconst isNewVisitor = !visitId || !visitorId;\r\n\r\n\tif (!visitId) {\r\n\t\tsetCookie('hawk_visit_id', createGuid(), getVisitExpiry());\r\n\t\tvisitId = getCookie('hawk_visit_id');\r\n\t}\r\n\r\n\tif (!visitorId) {\r\n\t\tsetCookie('hawk_visitor_id', createGuid(), getVisitorExpiry());\r\n\t\tvisitorId = getCookie('hawk_visitor_id');\r\n\t}\r\n\r\n\tif (isNewVisitor) {\r\n\t\tAxiosHelper.post('/ajax/hawksearch/identify', {\r\n\t\t\tvisitId: visitId,\r\n\t\t\tvisitorId: visitorId,\r\n\t\t});\r\n\t}\r\n\r\n\tconst payload = Object.assign(\r\n\t\t{\r\n\t\t\tClientGuid: HawkSearch.ClientGuid,\r\n\t\t\tVisitId: visitId,\r\n\t\t\tVisitorId: visitorId,\r\n\t\t\tTrackingProperties: HawkSearch.Context,\r\n\t\t\tCustomDictionary: HawkSearch.CustomContext,\r\n\t\t},\r\n\t\tdata,\r\n\t);\r\n\r\n\t// #region HCL\r\n\tAxiosHelper.post('/ajax/hawksearch/trackevent', { request: payload })\r\n\t\t// #endregion\r\n\t\t.then((response) => {\r\n\t\t\tconsole.log('Success:', response.statusText);\r\n\t\t})\r\n\t\t.catch((error: AxiosError) => {\r\n\t\t\tconsole.error('Error:', error);\r\n\t\t});\r\n}\r\n\r\n// TODO: add comments about what this is for? i think it has to do with timing between hawksearch.js and this script?\r\nfunction init() {\r\n\tif (window.HawkSearch && typeof window.HawkSearch.initCustomEvents === 'function') {\r\n\t\twindow.HawkSearch.initCustomEvents();\r\n\t}\r\n}\r\n\r\nif (document.readyState === 'complete' || document.readyState === 'interactive') {\r\n\tsetTimeout(init);\r\n} else {\r\n\tdocument.addEventListener('DOMContentLoaded', init);\r\n}\r\n\r\nclass ContextDictionary {\r\n\tadd(key: string, value: any) {\r\n\t\tthis[key] = value;\r\n\t}\r\n\r\n\tclear() {\r\n\t\tfor (const key in this) {\r\n\t\t\tthis.remove(key);\r\n\t\t}\r\n\t}\r\n\r\n\tremove(key: string) {\r\n\t\tif (this.hasOwnProperty(key)) {\r\n\t\t\tdelete this[key];\r\n\t\t}\r\n\t}\r\n\r\n\tpush(key: string, value: any) {\r\n\t\tif (this.hasOwnProperty(key)) {\r\n\t\t\tconst existingValue = this[key];\r\n\t\t\tthis[key] = `${existingValue},${value}`;\r\n\t\t} else {\r\n\t\t\tthis.add(key, value);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nconst Context = new ContextDictionary();\r\nconst CustomContext = new ContextDictionary();\r\n\r\n// initialize HawkSearch with values from RocHawkConfig\r\nif (!window.HawkSearch) {\r\n\twindow.HawkSearch = {\r\n\t\tClientGuid: RocHawkConfig.clientGuid,\r\n\t\tTrackingUrl: RocHawkConfig.trackingUrl,\r\n\t\tContext: Context,\r\n\t\tCustomContext: CustomContext,\r\n\t};\r\n}\r\n\r\nconst HawkSearch = window.HawkSearch;\r\n\r\nexport default {\r\n\tTracking: {\r\n\t\ttrack,\r\n\t\t// #region Commerce\r\n\t\ttrackCommerce,\r\n\t\t// #endregion\r\n\t},\r\n\tContext,\r\n\tCustomContext,\r\n};\r\n","// source: https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttributeNames\r\n/* eslint-disable no-var */\r\n(function () {\r\n\tif (Element.prototype.getAttributeNames == undefined) {\r\n\t\tElement.prototype.getAttributeNames = function () {\r\n\t\t\tvar attributes = this.attributes;\r\n\t\t\tvar length = attributes.length;\r\n\t\t\tvar result = new Array(length);\r\n\t\t\tfor (var i = 0; i < length; i++) {\r\n\t\t\t\tresult[i] = attributes[i].name;\r\n\t\t\t}\r\n\t\t\treturn result;\r\n\t\t};\r\n\t}\r\n})();\r\n","import React from 'react';\r\nimport ReactDOM from 'react-dom';\r\nimport ErrorBoundary from './ErrorBoundary';\r\nimport { toCamelCase } from 'util/StringUtil';\r\nimport 'shared/polyfills/getAttributeNames';\r\nimport Spinner from 'shared/components/Spinner';\r\n\r\ninterface AttributeProps {\r\n\t[index: string]: string;\r\n}\r\n\r\nfunction getDataPropsFromAttributes(element: Element): AttributeProps {\r\n\tconst props: AttributeProps = {};\r\n\r\n\tconst dataAttributePrefix = 'data-';\r\n\r\n\tconst attributeNames = element.getAttributeNames().filter((s) => s.startsWith(dataAttributePrefix));\r\n\tfor (const attributeName of attributeNames) {\r\n\t\tconst strippedName = toCamelCase(attributeName.substring(dataAttributePrefix.length));\r\n\t\tprops[strippedName] = element.getAttribute(attributeName) ?? '';\r\n\t}\r\n\r\n\treturn props;\r\n}\r\n\r\n/**\r\n * A helper function to facilitate initializing react applications on top of server-side rendered elements.\r\n * @param getReactElement Function that returns the react component to render.\r\n * @param elementId The ID of the DOM element being targeted.\r\n */\r\nexport const initReactApp = (getReactElement: (props: unknown) => React.ReactElement, elementId: string) => {\r\n\tif (typeof getReactElement !== 'function' || !elementId) {\r\n\t\treturn () => {\r\n\t\t\tconsole.warn('A react element generator function and element ID are required.');\r\n\t\t};\r\n\t}\r\n\r\n\tconst element = document.getElementById(elementId);\r\n\r\n\tif (!element) {\r\n\t\treturn () => {\r\n\t\t\tconsole.warn(\r\n\t\t\t\t`Element with ID '${elementId}' was not found. Did you forget to render it on the server or is this entry point not supposed to run?`,\r\n\t\t\t);\r\n\t\t};\r\n\t}\r\n\r\n\treturn () => {\r\n\t\tconst props = getDataPropsFromAttributes(element);\r\n\t\tconsole.debug(`Rendering application inside element with ID ${elementId}.`);\r\n\t\tReactDOM.render(\r\n\t\t\t}>\r\n\t\t\t\t{getReactElement(props)}\r\n\t\t\t,\r\n\t\t\telement,\r\n\t\t);\r\n\t};\r\n};\r\n\r\nexport const initReactAppByAttribute = (\r\n\tgetReactElement: (props: unknown, domElement: Element) => React.ReactElement,\r\n\tattribute: string,\r\n) => {\r\n\tif (typeof getReactElement !== 'function' || !attribute) {\r\n\t\treturn () => {\r\n\t\t\tconsole.warn('A react element generator function and element ID are required.');\r\n\t\t};\r\n\t}\r\n\r\n\tconst elements = document.querySelectorAll(`[${attribute}]`);\r\n\r\n\tif (!elements || elements.length == 0) {\r\n\t\treturn () => {\r\n\t\t\tconsole.warn(\r\n\t\t\t\t`No elements with data attribute '${attribute}' were found. Did you forget to render it on the server or is this entry point not supposed to run?`,\r\n\t\t\t);\r\n\t\t};\r\n\t}\r\n\r\n\treturn () => {\r\n\t\tfor (let i = 0; i < elements.length; ++i) {\r\n\t\t\tconst element = elements[i];\r\n\t\t\tconst props = getDataPropsFromAttributes(element);\r\n\t\t\tconsole.debug(`Rendering application inside element with attribute ${attribute}.`);\r\n\t\t\tReactDOM.render(\r\n\t\t\t\t}>\r\n\t\t\t\t\t{getReactElement(props, element)}\r\n\t\t\t\t,\r\n\t\t\t\telement,\r\n\t\t\t);\r\n\t\t}\r\n\t};\r\n};\r\n","/**\r\n * @see HawkSearchConfig.apiUrl\r\n */\r\nexport const defaultApiUrl = 'https://searchapi-dev.hawksearch.net';\r\n\r\n/**\r\n * @see HawkSearchConfig.dashboardUrl\r\n */\r\nexport const defaultDashboardUrl = 'https://dev.hawksearch.net';\r\n\r\n/**\r\n * @see HawkSearchConfig.searchUrl\r\n */\r\nexport const defaultSearchUrl = '/api/v2/search';\r\n\r\n/**\r\n * @see HawkSearchConfig.autocompleteUrl\r\n */\r\nexport const defaultAutocompleteUrl = '/api/autocomplete';\r\n\r\n/**\r\n * @see HawkSearchConfig.searchPageUrl\r\n */\r\nexport const defaultSearchPageUrl = '/search';\r\n\r\n/**\r\n * Endpoint for hawksearch's compare api\r\n */\r\nexport const defaultCompareItemsURL = '/api/v2/compare';\r\n\r\n/**\r\n * @see HawkSearchConfig.recommendationUrl\r\n */\r\nexport const defaultRecommendationUrl = 'https://recs-dev.hawksearch.net';\r\n\r\n/**\r\n * @see HawkSearchConfig.recommendationWidgetUrl\r\n */\r\nexport const recommendationWidgetUrl = '/api/recommendation/v2/getwidgetitems';\r\n\r\n// #region HCL\r\n/**\r\n * @see HawkSearchConfig.enableRemovingDashesFromSearchKeyword\r\n */\r\nexport const enableRemovingDashesFromSearchKeyword = false;\r\n// #endregion\r\n","/**\r\n * Returns visitor expiry date for hawksearch visitor id stored in the cookie for the user.\r\n */\r\nexport function getVisitorExpiry() {\r\n\tconst d = new Date();\r\n\t// 1 year\r\n\td.setTime(d.getTime() + 360 * 24 * 60 * 60 * 1000);\r\n\treturn d.toUTCString();\r\n}\r\n\r\n/**\r\n * Returns visitor expiry date for hawksearch visit id stored in the cookie for the user.\r\n */\r\nexport function getVisitExpiry() {\r\n\tconst d = new Date();\r\n\t// 4 hours\r\n\td.setTime(d.getTime() + 4 * 60 * 60 * 1000);\r\n\treturn d.toUTCString();\r\n}\r\n\r\n/**\r\n * Creates GUID.\r\n */\r\nexport function createGuid() {\r\n\tconst s: string[] = [];\r\n\tconst hexDigits = '0123456789abcdef';\r\n\tfor (let i = 0; i < 36; i++) {\r\n\t\ts[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);\r\n\t}\r\n\ts[14] = '4'; // bits 12-15 of the time_hi_and_version field to 0010\r\n\ts[19] = hexDigits.substr(((s[19] as any) & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01\r\n\ts[8] = s[13] = s[18] = s[23] = '-';\r\n\r\n\treturn s.join('');\r\n}\r\n\r\n/**\r\n * Returns the cookie.\r\n */\r\nexport function getCookie(name) {\r\n\tconst nameEQ = name + '=';\r\n\tconst ca = document.cookie.split(';');\r\n\r\n\tfor (let i = 0; i < ca.length; i++) {\r\n\t\tlet cookie = ca[i];\r\n\r\n\t\twhile (cookie.charAt(0) == ' ') {\r\n\t\t\tcookie = cookie.substring(1, cookie.length);\r\n\t\t}\r\n\r\n\t\tif (cookie.indexOf(nameEQ) == 0) {\r\n\t\t\treturn cookie.substring(nameEQ.length, cookie.length);\r\n\t\t}\r\n\t}\r\n\treturn null;\r\n}\r\n\r\n/**\r\n * Sets the cookie.\r\n */\r\nexport function setCookie(name: string, value: string, expiry?: string) {\r\n\tlet expires = '';\r\n\r\n\tif (expiry) {\r\n\t\texpires = '; expires=' + expiry;\r\n\t}\r\n\r\n\tdocument.cookie = name + '=' + value + expires + '; path=/';\r\n}\r\n","/**\r\n * THIS HAS A COPY ON ROC.WEB. DO NOT MAKE CHANGES HERE WITHOUT ALSO MAKING THEM IN THE OTHER FILE.\r\n *\r\n * THIS MUST ALSO BE KEPT IN SYNC WITH THE \"RazorDisplayPrice\" VIEW COMPONENT.\r\n *\r\n * DIVERGENCES:\r\n * - The style \"visually-hidden\" DOES NOT EXIST ON ROC.WEB. Change this to \"roc-visually-hidden\"\r\n */\r\n\r\nimport classnames from 'classnames';\r\nimport React from 'react';\r\nimport { Localizer } from 'services/Localizer';\r\nimport { CssClasses, ProductPricingProps } from 'shared-client/types/commerce/product-details';\r\nimport {\r\n\tAmbiguousDisplayPrice,\r\n\tMissingDisplayPrice,\r\n\tPartialDisplayPrice,\r\n\tPrice,\r\n\tPriceDisplayRule,\r\n\tPriceSpan,\r\n\tSimpleDisplayPrice,\r\n} from 'shared-client/types/commerce/display-price';\r\n\r\nimport { PricingResourceKeys } from 'features/commerce/pricing/resources';\r\n\r\nconst GetCssClasses = (className: string | undefined, inline: boolean) => {\r\n\tconst priceClass = ['roc-pricing__price', className ? className + '__price' : null];\r\n\r\n\treturn {\r\n\t\tbase: ['roc-pricing', { 'roc-pricing--inline': inline }, className ? className : null],\r\n\t\tnormalPrice: ['roc-pricing__price', className ? className + '__price' : null],\r\n\t\tcrossedOutPrice: [\r\n\t\t\tpriceClass,\r\n\t\t\t'roc-pricing__price--original',\r\n\t\t\tclassName ? className + '__price--original' : null,\r\n\t\t],\r\n\t\thighlightedPrice: [priceClass, 'roc-pricing__price--sale', className ? className + '__price--sale' : null],\r\n\t};\r\n};\r\n\r\n/**\r\n * Renders a product price. This could be a simple price \"$4.99\", a price that's on sale \"~~$4.99~~ $3.99\",\r\n * a range of prices, an ambiguous price or potentially others.\r\n *\r\n * The pricing information is expected to have come from the server where it has already been validated.\r\n * It is the responsibility of the caller to verify pricing objects passed to ProductPricing are valid.\r\n */\r\nexport default function ProductPricing(props: ProductPricingProps) {\r\n\t// #region HCL\r\n\tconst { displayPrice, className, inline = false, testId = 'product-price', roundValue } = props;\r\n\t// #endregion\r\n\r\n\t// The server/caller is trusted to have provided valid props.\r\n\t// Do no validation here.\r\n\r\n\tif (displayPrice == null) {\r\n\t\t// Missing price. Remove this if MissingPrice functionality is ever needed beyond \"don't render\"\r\n\t\treturn null;\r\n\t}\r\n\r\n\tconst css = GetCssClasses(className, inline);\r\n\r\n\tlet renderResult: JSX.Element | null;\r\n\tswitch (displayPrice.displayRule) {\r\n\t\tcase PriceDisplayRule.Missing:\r\n\t\t\trenderResult = renderMissingPrice(css, displayPrice);\r\n\t\t\tbreak;\r\n\r\n\t\tcase PriceDisplayRule.Normal:\r\n\t\t\trenderResult = renderNormalPrice(css, displayPrice, testId);\r\n\t\t\tbreak;\r\n\r\n\t\tcase PriceDisplayRule.AmbiguousRange:\r\n\t\t\t// #region HCL\r\n\t\t\trenderResult = renderAmbiguousPrice(css, displayPrice, testId, roundValue);\r\n\t\t\t// #endregion\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\t\tthrow new Error('Erroneous price display rule');\r\n\t}\r\n\r\n\treturn (\r\n\t\t\r\n\t\t\t{renderResult}\r\n\t\t\r\n\t);\r\n}\r\n\r\n/**\r\n * Renders a missing price, eg nothing. This currently renders nothing but could be updated to render \"Not For Sale\" for example.\r\n * @param css The set of css rules that can be applied.\r\n * @param price The price object\r\n */\r\n// eslint-disable-next-line no-unused-vars\r\nfunction renderMissingPrice(css: CssClasses, price: MissingDisplayPrice) {\r\n\treturn null;\r\n}\r\n\r\n/**\r\n * Renders a normal price. This is a price that might be on sale and may either be a unit price (eg $4.99) or a\r\n * range (eg $3.99 - $7.99).\r\n * @param css The set of css rules that can be applied.\r\n * @param price The price object\r\n */\r\nfunction renderNormalPrice(css: CssClasses, price: SimpleDisplayPrice, testId: string) {\r\n\t// conditionally cross out the base price\r\n\tconst basePriceClass = price.salePrice != null ? css.crossedOutPrice : css.normalPrice;\r\n\r\n\treturn (\r\n\t\t<>\r\n\t\t\t\r\n\t\t\t\t{Localizer('OriginalPrice')}\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t{price.salePrice != null ? (\r\n\t\t\t\t\r\n\t\t\t\t\t{Localizer('SalePrice')}\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t) : null}\r\n\t\t\r\n\t);\r\n}\r\n\r\n/**\r\n * Renders an ambiguous price. This is a compound price representing multiple different products where the upperbound of the price\r\n * can't be reported in a useful way. The units of measure between the base and sale price may be different.\r\n * @param css The set of css rules that can be applied.\r\n * @param price The price object\r\n */\r\n// #region HCL\r\nfunction renderAmbiguousPrice(css: CssClasses, price: AmbiguousDisplayPrice, testId: string, roundValue?: boolean) {\r\n\t// #endregion\r\n\t// conditionally cross out the base price\r\n\tconst basePriceClass = price.salePrice != null ? css.crossedOutPrice : css.normalPrice;\r\n\t// #region HCL\r\n\tconst roundedPrice = roundValue ? price.basePrice.rawValue.toFixed(2) : price.basePrice.value;\r\n\t// #endregion\r\n\treturn (\r\n\t\t<>\r\n\t\t\t\r\n\t\t\t\t{Localizer('OriginalPrice')}\r\n\t\t\t\t\r\n\t\t\t\t\t{/* #region HCL */}\r\n\t\t\t\t\t\r\n\t\t\t\t\t{/* #region HCL */}\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\t{price.salePrice != null ? (\r\n\t\t\t\t\r\n\t\t\t\t\t{Localizer('SalePrice')}\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t) : null}\r\n\t\t\r\n\t);\r\n}\r\n\r\n/**\r\n * Renders a partial display price (eg it may be either a simple price or a range price)\r\n */\r\nfunction VariantPriceComponent({ price }: { price: PartialDisplayPrice }) {\r\n\tconst label = price.unit?.label;\r\n\r\n\tswitch (typeof price.value) {\r\n\t\tcase 'string':\r\n\t\t\treturn ;\r\n\r\n\t\tcase 'object':\r\n\t\t\treturn ;\r\n\t}\r\n}\r\n\r\nfunction FormatAmbiguousPriceSpan(props: { price: Price; unitName: string }) {\r\n\t// Ambiguous prices always have a unit of measure. It is never optional.\r\n\treturn <>{Localizer('AmbiguousPriceRangeWithUnit', props.price, props.unitName)};\r\n}\r\n\r\n/**\r\n * Renders a price range (eg $14.99 - $19.99) with an optional unit of measure\r\n */\r\nfunction FormatPriceSpan(props: { priceRange: PriceSpan; unitName: string | undefined }) {\r\n\treturn props.unitName != null ? (\r\n\t\t<>\r\n\t\t\t{Localizer(\r\n\t\t\t\t'PriceRangeWithUnit',\r\n\t\t\t\tprops.priceRange.from,\r\n\t\t\t\tprops.priceRange.to,\r\n\t\t\t\tprops.unitName,\r\n\t\t\t)}\r\n\t\t\r\n\t) : (\r\n\t\t<>{Localizer('PriceRangeWithoutUnit', props.priceRange.from, props.priceRange.to)}\r\n\t);\r\n}\r\n\r\n/** Formats the price with the unit of measure (if present) appended. */\r\nfunction FormatPrice(props: { price: Price; unitName?: string }) {\r\n\treturn props.unitName != null ? (\r\n\t\t<>{Localizer('PriceWithUnit', props.price, props.unitName)}\r\n\t) : (\r\n\t\t<>{Localizer('PriceWithoutUnit', props.price)}\r\n\t);\r\n}\r\n","import { useState, useEffect } from 'react';\r\n\r\n/**\r\n * Reusable hook that returns true after a certain amount of time has passed. Useful to delay\r\n * displaying components in render functions.\r\n *\r\n * @export\r\n * @param {number} [waitMs=200]\r\n * @returns\r\n */\r\nexport default function useDelayedDisplay(waitMs: number = 200) {\r\n\tconst [display, setDisplay] = useState(false);\r\n\r\n\tuseEffect(() => {\r\n\t\t// after a set amount of time, show the spinner\r\n\t\tconst timeout = setTimeout(() => {\r\n\t\t\tsetDisplay(true);\r\n\t\t}, waitMs);\r\n\r\n\t\treturn () => {\r\n\t\t\tclearTimeout(timeout);\r\n\t\t};\r\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\r\n\t}, []);\r\n\r\n\treturn display;\r\n}\r\n","import { RocEventType, RocEvent, ExtractEventParameters } from 'shared/events';\r\n\r\n/**\r\n * Helper function for handling ROC events from non React functions.\r\n * @param eventType The type of event to handle\r\n * @param eventHandler The event handler\r\n * @returns The callback function to remove this handler\r\n */\r\nexport default function addRocEventHandler(\r\n\teventType: T,\r\n\teventHandler: (data: ExtractEventParameters) => void,\r\n): () => void {\r\n\tconst handler = (evt: CustomEvent): void => {\r\n\t\teventHandler(evt.detail);\r\n\t};\r\n\r\n\tdocument.addEventListener(eventType, handler);\r\n\r\n\treturn () => document.removeEventListener(eventType, handler);\r\n}\r\n","import { PricingResult } from './pricing-result';\r\n\r\n/**\r\n * Represents a display pricing service result containing all necessary details to render a set of product prices.\r\n */\r\nexport type DisplayPricingResult = PricingResult;\r\n\r\n/**\r\n * Represents a simple price intended to be rendered.\r\n * Comparisons and arithmetic between prices is illegal besides !== and ===.\r\n * This is not suitable for transactions and attempting to use this for transactions is erroneous.\r\n */\r\nexport type Price = string;\r\n\r\n/**\r\n * Represents an inclusive range of prices. It is erroneous for a price span no length (eg the\r\n * from and to field are the same), as this should be represented by a @see Price instead.\r\n *\r\n * PriceSpan is typically used for ambiguous ranges\r\n */\r\nexport type PriceSpan = {\r\n\t/**\r\n\t * The lower bound of the price. If this is associated with a group of products, this\r\n\t * is the price of the cheapest associated product.\r\n\t */\r\n\tfrom: Price;\r\n\r\n\t/**\r\n\t * The upper bound of the price. If this is associated with a group of products, this\r\n\t * is the price of the most expensive associated product.\r\n\t */\r\n\tto: Price;\r\n};\r\n\r\n/**\r\n * Represents a displayable price of unknown type.\r\n */\r\nexport type VariantPrice = Price | PriceSpan;\r\n\r\n/**\r\n * The display rules for rendering a price on the frontend.\r\n */\r\nexport enum PriceDisplayRule {\r\n\t/**\r\n\t * Represents a lack of a price. This is typically used for a product\r\n\t * that isn't purchaseable. Distinct from free.\r\n\t *\r\n\t * If a price is missing, it is illegal to use any display price type besides @see MissingPrice\r\n\t */\r\n\tMissing = 'Missing',\r\n\r\n\t/**\r\n\t * Represents a normal price or price range. Expected price types are @see PriceSpan and @see Price\r\n\t */\r\n\tNormal = 'Normal',\r\n\r\n\t/**\r\n\t * Represents a price without a clearly defined upperbound. This can happen if multiple products in a group product\r\n\t * do not share a common unit of measure. Expected price types are @see Price\r\n\t */\r\n\tAmbiguousRange = 'AmbiguousRange',\r\n}\r\n\r\n/**\r\n * Represents a pricing object that is guaranteed to have a base price\r\n */\r\nexport interface HasBasePrice {\r\n\t/** The price of the product if it isn't on sale. */\r\n\tbasePrice: PartialDisplayPrice;\r\n}\r\n\r\n/**\r\n * Represents a pricing object that is guaranteed to have a sale price\r\n */\r\nexport interface HasSalePrice {\r\n\t/** The sale price of the product. This is always less than the base price. */\r\n\tsalePrice: PartialDisplayPrice;\r\n}\r\n\r\n/**\r\n * Represents a pricing object that has no base price, that is, it cannot be purchased.\r\n */\r\nexport interface HasNoBasePrice {\r\n\t/** The item in question has no base price and as such, it is illegal to access it. */\r\n\tbasePrice?: never;\r\n}\r\n\r\n/**\r\n * Represents a pricing object that has no sale price\r\n */\r\nexport interface HasNoSalePrice {\r\n\t/** The item in question has no sale price and as such, it is illegal to access it. */\r\n\tsalePrice?: never;\r\n}\r\n\r\n/**\r\n * Represents a \"primitive\" price object that would be displayed.\r\n * A product that has a base price and a sale price would have two unit display prices for example.\r\n */\r\nexport type PartialDisplayPrice = TPrice extends Price\r\n\t? UnitPrice & HasRawValue\r\n\t: UnitPrice;\r\n\r\ninterface UnitPrice {\r\n\t/** The unit of measure of the item/product being sold. This is typically appended to a price to yield a value like \"$2.99/ea\" */\r\n\tunit?: { label: string };\r\n\r\n\t/** The price value to be displayed. */\r\n\tvalue: TPrice;\r\n\r\n\t// #region HCL - added availability to pass rawValue\r\n\trawValue?: number;\r\n\t// #endregion\r\n}\r\n\r\ninterface HasRawValue {\r\n\t/**\r\n\t * The raw price value for use in comparing prices to eachother or checking if they are zero or negative.\r\n\t * It is not safe to assume this value for display purposes or price calculations.\r\n\t */\r\n\trawValue: number;\r\n}\r\n\r\n/**\r\n * Constrains a VariantPrice to a more specific price type\r\n */\r\ntype Filter = T extends U ? T : never;\r\n\r\n/**\r\n * Represents a price object that can be displayed.\r\n */\r\nexport type DisplayPrice<\r\n\tTBasePrice extends VariantPrice = VariantPrice,\r\n\tTSalePrice extends VariantPrice = TBasePrice\r\n> =\r\n\t| SimpleDisplayPrice\r\n\t| AmbiguousDisplayPrice, Filter>\r\n\t| MissingDisplayPrice;\r\n\r\n/**\r\n * Represents a missing price, typically if used on an object not for a sale or an erroneous object.\r\n * This would either not be rendered or be rendered as \"Not For Sale\"\r\n */\r\nexport interface MissingDisplayPrice {\r\n\t/** The display rules for rendering a price on the frontend.\r\n\t *\r\n\t * A \"missing\" or \"invisible\" price is for a product that is not on sale and thus should not have\r\n\t * a price rendered on screen */\r\n\tdisplayRule: PriceDisplayRule.Missing;\r\n}\r\n\r\n/**\r\n * Represents a simple price, that is a price that might be on sale with fixed upper and lower bounds. The unit\r\n * of measure for the base and sale price (if present) is expected to be the same\r\n */\r\nexport interface SimpleDisplayPrice<\r\n\tTBasePrice extends VariantPrice = VariantPrice,\r\n\tTSalePrice extends VariantPrice = TBasePrice\r\n> extends HasBasePrice,\r\n\t\tPartial> {\r\n\t/** The display rules for rendering a price on the frontend.\r\n\t *\r\n\t * A normal price is either a simple price like \"$3.12/ea\" or a range like \"$2.00-$5.00/ea\"\r\n\t */\r\n\tdisplayRule: PriceDisplayRule.Normal;\r\n}\r\n\r\n/**\r\n * Represents a price without a predictable upperbound for the price. This would typically be used if a group of products\r\n * didn't have a common unit of measure.\r\n */\r\nexport interface AmbiguousDisplayPrice\r\n\textends HasBasePrice,\r\n\t\tPartial> {\r\n\t/** The display rules for rendering a price on the frontend.\r\n\t *\r\n\t * An ambiguous price doesn't have a a specifiable upperbound because there isn't a common unit of measure\r\n\t * to use as a baseline for what the most expensive unit of measure is. This is will appear like \"From $2.00\"\r\n\t */\r\n\tdisplayRule: PriceDisplayRule.AmbiguousRange;\r\n}\r\n","import { DisplayPricingResult, Price, SimpleDisplayPrice } from 'shared-client/types/commerce/display-price';\r\nimport { UnitOfMass } from 'shared-client/types/commerce/product-details';\r\nimport { BreadcrumbItem } from 'shared/components/Breadcrumbs';\r\nimport { PartialDataLoaderOptions } from 'shared/data/usePartialDataLoader';\r\nimport { BasePartialDetailsState } from 'shared/types';\r\nimport { Asset } from 'shared/assets/types';\r\n\r\nexport function getInitialProductDetailsState(): ProductDetailsState {\r\n\treturn window.__ROC_COMMERCE_PRODUCT_DETAILS__ ?? {};\r\n}\r\n\r\ndeclare global {\r\n\tinterface Window {\r\n\t\t__ROC_COMMERCE_PRODUCT_DETAILS__: ProductDetailsState;\r\n\t}\r\n}\r\n\r\nexport interface ProductDetailsState extends BasePartialDetailsState {\r\n\tsummary: Summary;\r\n\r\n\tassets?: ProductAsset[] | null;\r\n\r\n\tavailability?: Availability | null;\r\n\r\n\tbrand?: Brand | null;\r\n\r\n\t/**\r\n\t * Represents the visible tabs for the current product\r\n\t */\r\n\ttabs?: TabViewChunk[];\r\n\r\n\tselections?: ProductDetailSelection[];\r\n\r\n\tchildren?: SimpleProduct[];\r\n\r\n\trelatedProducts?: RelatedProduct[];\r\n\r\n\treviewsSummary: ReviewSummaryDto;\r\n\r\n\t/**\r\n\t * The available pricing lines for the product as well as the selected pricing line state\r\n\t */\r\n\tpricingLines?: ProductPricingLinesDetails;\r\n\r\n\t/**\r\n\t * The pricing result tree containing renderable prices for the product.\r\n\t */\r\n\tdisplayPricing?: DisplayPricingResult;\r\n\r\n\tbreadcrumbPath?: BreadcrumbItem[];\r\n\r\n\t/**\r\n\t * Information about the available product add ons for the product, and for child products, if this is a group\r\n\t */\r\n\taddOns?: AddOnsPdpDto;\r\n\r\n\tisNewProduct: boolean;\r\n}\r\n\r\n/**\r\n * Single add on data.\r\n */\r\nexport interface ProductAddOnDto {\r\n\t/**\r\n\t * The id of the product add on.\r\n\t */\r\n\tvalue: string;\r\n\r\n\t/**\r\n\t * The name of the product add on.\r\n\t */\r\n\tlabel: string;\r\n\r\n\t/**\r\n\t * The SKU of the product add on.\r\n\t */\r\n\tsku: string;\r\n\r\n\t/**\r\n\t * The description of the product add on.\r\n\t */\r\n\tdescription: string;\r\n\r\n\t/**\r\n\t * Represents if the current add on is required to add a product to cart.\r\n\t */\r\n\trequired: boolean;\r\n\r\n\t/**\r\n\t * Represents if the current add on is selected\r\n\t */\r\n\tselected: boolean;\r\n\r\n\t/**\r\n\t * Represents if the current add on is updated\r\n\t */\r\n\tisModified: boolean;\r\n\r\n\t/**\r\n\t * Represents the add on attributes\r\n\t */\r\n\tattributes: AddOnAttributeDto[];\r\n\r\n\t/**\r\n\t * The add on main image thumbnail.\r\n\t */\r\n\tthumbnailUrl: string;\r\n\r\n\t/**\r\n\t * The add on main image alt text.\r\n\t */\r\n\taltText: string;\r\n\r\n\t/**\r\n\t * The displayable price of a single unit of this line item.\r\n\t */\r\n\tunitPrice?: SimpleDisplayPrice;\r\n}\r\n\r\n/**\r\n * Product add on single attribute data\r\n */\r\nexport interface AddOnAttributeDto {\r\n\t/**\r\n\t * Product add on attribute id\r\n\t */\r\n\tvalue: string;\r\n\r\n\t/**\r\n\t * Product add on attribute name\r\n\t */\r\n\tlabel: string;\r\n\r\n\t/**\r\n\t * Represents if the add on attribute value is required\r\n\t */\r\n\trequired: boolean;\r\n\r\n\t/**\r\n\t * Product add on attribute instruction\r\n\t */\r\n\tinstructions: string;\r\n\r\n\t/**\r\n\t * Product add on attribute input type\r\n\t */\r\n\tinputAttributeType: InputAttributeType | null;\r\n\r\n\t/**\r\n\t * The maximum length constraint for the add on attribute value\r\n\t */\r\n\tmaximumLength: number | null;\r\n\r\n\t/**\r\n\t * The minimum length constraint for the add on attribute value\r\n\t */\r\n\tminimumLength: number | null;\r\n\r\n\t/**\r\n\t * The maximum number of line constraint for the add on attribute value\r\n\t * used for multiline attributes\r\n\t */\r\n\tmaximumNumberOfLines: number | null;\r\n\r\n\t/**\r\n\t * The default value of the add on attribute value\r\n\t */\r\n\tdefaultValue: string;\r\n\r\n\t/**\r\n\t * The entered value for the current attribute\r\n\t */\r\n\tdata: string;\r\n\r\n\t/**\r\n\t * The add on attribute selectable values\r\n\t */\r\n\tvalues: AttributeValueDto[];\r\n}\r\n\r\n/**\r\n * The add on attribute input type\r\n */\r\nexport enum InputAttributeType {\r\n\tSingle = 'Single',\r\n\tMultiline = 'Multiline',\r\n}\r\n\r\n/**\r\n * Single add on attribute selectable value\r\n */\r\nexport interface AttributeValueDto {\r\n\t/**\r\n\t * The add on attribute selectable value id\r\n\t */\r\n\tvalue: string;\r\n\r\n\t/**\r\n\t * The add on attribute selectable value label\r\n\t */\r\n\tlabel: string;\r\n\r\n\t/**\r\n\t * Represents if the current selectable value is selected\r\n\t */\r\n\tselected: boolean;\r\n}\r\n\r\nexport interface Summary {\r\n\tname: string;\r\n\ttype: ProductType;\r\n\tsku?: string;\r\n\tmanufacturerPartNumber?: string;\r\n\tproductUrl: string;\r\n\tdescription?: string;\r\n\tmeta?: Meta;\r\n\tproductGroupId: string | null;\r\n\t/**\r\n\t * \tFlag defining if the current product should use the alternate product details.\r\n\t */\r\n\tuseAlternateProductDetails?: boolean;\r\n\t// #region HCL\r\n\tproductGroupName?: string;\r\n\t// #endregion\r\n}\r\n\r\nexport interface Meta {\r\n\turl: string;\r\n\tpageTitle?: string;\r\n\tmetaKeywords?: string;\r\n\tmetaDescription?: string;\r\n\tnoIndex: boolean;\r\n\tnoFollow: boolean;\r\n}\r\n\r\nexport interface Availability {\r\n\tbackOrder: boolean;\r\n\toutOfStock: boolean;\r\n\t// #region HCL\r\n\tcallForAvailability: boolean;\r\n\t// #endregion\r\n}\r\n\r\n/**\r\n * Product Review Summary DTO\r\n */\r\nexport interface ReviewSummaryDto {\r\n\t/**\r\n\t * The average rating of the product. If undefined, the product has no reviews with ratings.\r\n\t */\r\n\taverageRating?: number;\r\n\r\n\t/**\r\n\t * The number of public reviews for the product\r\n\t */\r\n\treviewCount: number;\r\n}\r\n\r\nexport interface ProductAsset extends Asset {\r\n\t/**\r\n\t * The alternate text associated with the image\r\n\t */\r\n\taltText: string;\r\n\t/**\r\n\t * The main image URL\r\n\t */\r\n\tmainImageUrl: string;\r\n\t/**\r\n\t * The thumbnail URL\r\n\t */\r\n\tthumbnailUrl: string;\r\n\t/**\r\n\t * The enlarged image URL\r\n\t */\r\n\tenlargedImageUrl: string;\r\n\t/**\r\n\t * The sort order for this image\r\n\t */\r\n\tsortOrder: number;\r\n\t/**\r\n\t * Embedded URL for external media asset\r\n\t */\r\n\tembeddedUrl: string;\r\n}\r\n\r\nexport interface Brand {\r\n\tname: string;\r\n\tlogoUrl: string | null;\r\n}\r\n\r\nexport interface TabViewChunk {\r\n\ttab: Tab;\r\n\tmodel: T;\r\n\trawHtml?: string;\r\n}\r\n\r\nexport interface Tab {\r\n\tid: string;\r\n\tdisplayName: string;\r\n\ttabType: string;\r\n\tsortOrder: number;\r\n\tname: string;\r\n}\r\n\r\nexport interface TabViewModel {\r\n\tviewName: string;\r\n\tmodel: T;\r\n}\r\n\r\nexport interface ProductDetailSelection {\r\n\tlabel: string;\r\n\tvalues: SelectionValue[];\r\n\r\n\t/**\r\n\t * The selected attribute field name used for adding info to hawk context\r\n\t */\r\n\tfield: string;\r\n}\r\n\r\n/**\r\n * Represents a simple selection DTO object\r\n */\r\nexport interface SimpleSelectionDto {\r\n\t/**\r\n\t * The Code of the product attribute\r\n\t */\r\n\tid: string;\r\n\r\n\t/**\r\n\t * The Name of the product attribute\r\n\t */\r\n\tname: string;\r\n\r\n\t/**\r\n\t * The Id of the attribute value\r\n\t */\r\n\tvalue: string;\r\n\r\n\t/**\r\n\t * The Name of the attribute value\r\n\t */\r\n\tlabel: string;\r\n\r\n\t/**\r\n\t * The selected attribute field name used for adding info to hawk context\r\n\t */\r\n\tfield: string;\r\n}\r\n\r\nexport interface SelectionValue {\r\n\tvalue: string;\r\n\tlabel: string;\r\n\tvalid: boolean;\r\n\tchecked: boolean;\r\n\t// #region HCL\r\n\tswatchUrl: string;\r\n\t// #endregion\r\n}\r\n\r\nexport interface SimpleProduct {\r\n\tid: string;\r\n\tname: string;\r\n\t//#region HCL\r\n\tsku: string;\r\n\t//#endregion\r\n\tselections: string[];\r\n}\r\n\r\nexport interface RelatedProduct {\r\n\tid: string;\r\n\tname: string;\r\n\tdescription: string | null;\r\n\turl: string;\r\n\tmainImage: ProductAsset | null;\r\n}\r\n\r\nexport interface ProductSelectionDispatcherDto {\r\n\tproductId: string;\r\n\tproductDetails: ProductDetailsState;\r\n}\r\n\r\nexport interface AddOnsPdpDto {\r\n\t/**\r\n\t * The list of available product add-ons for the product.\r\n\t */\r\n\tproductAddOnData?: ProductAddOnDto[];\r\n\t/**\r\n\t * A list of add-ons available for child products, if this is a group product\r\n\t */\r\n\tavailableChildProductAddOns?: string[];\r\n}\r\n\r\n/*\r\n\tShirt Size: Small, Large\r\n\tColor: Red, Green\r\n\r\n\tScenario #1: All selections match\r\n\r\n\tValid selections:\r\n\tSmall, Red\r\n\tSmall, Green\r\n\tLarge, Red\r\n\tLarge, Green\r\n\r\n\t1. Pick Size\r\n\t2. Pick Color\r\n\t3. Find match and load child\r\n\r\n\tScenario #2: Selections mismatch\r\n\r\n\tValid selections:\r\n\tSmall, Red\r\n\tSmall, Green\r\n\tLarge, Red\r\n\r\n\t1. Pick Size (Small/Large)\r\n\t2. if Large, mark green as invalid\r\n\t3. if Small, show all colors\r\n\t4. Find match and load child\r\n\r\n\tScenario #3: Selections mismatch 2\r\n\r\n\tValid selections:\r\n\tSmall, Red\r\n\tSmall, Green\r\n\tLarge, Red\r\n\r\n\t1. Pick Green, mark large as invalid\r\n\t2. Pick Size\r\n\t3. Find match and load child\r\n\r\n\tScenario #4: Selections mismatch 3\r\n\r\n\tValid selections:\r\n\tSmall, Red\r\n\tSmall, Green\r\n\tLarge, Red\r\n\r\n\t1. Pick Green, mark large as invalid\r\n\t2. Pick Large anyway, remove color selection\r\n\t3. ...\r\n\t4. Find match and load child\r\n\r\n*/\r\n\r\n/**\r\n * All available product types\r\n *\r\n * @export\r\n */\r\nexport enum ProductType {\r\n\tSimple = 'Simple',\r\n\tGroup = 'Group',\r\n\tKit = 'Kit',\r\n\tGiftCard = 'GiftCard',\r\n}\r\n\r\nexport type ProductPartialDataLoaderOptions = Pick<\r\n\tPartialDataLoaderOptions,\r\n\t'initialState' | 'dataLoaderFn'\r\n>;\r\n\r\nexport interface ProductSelection {\r\n\t/**\r\n\t * The code of the product attribute\r\n\t */\r\n\tid: string;\r\n\t/**\r\n\t * The name of the product attribute\r\n\t */\r\n\tname: string;\r\n\t/**\r\n\t * The attribute value name (if available), otherwise attribute value value\r\n\t */\r\n\tlabel: string;\r\n\t/**\r\n\t * The id (Guid) of the attribute value\r\n\t */\r\n\tvalue: string;\r\n\r\n\t/**\r\n\t * The selected attribute field name used for adding info to hawk context\r\n\t */\r\n\tfield: string;\r\n}\r\n\r\n/**\r\n * Base unit of measure\r\n */\r\nexport interface UnitOfMeasure {\r\n\tname: string;\r\n\tdisplayName: string;\r\n}\r\n\r\n/**\r\n * Represents a single pricing line for a product (one of potentially many choices for purchasing a product)\r\n */\r\nexport type ProductPricingLine = {\r\n\t/**\r\n\t * The pricing line's id\r\n\t */\r\n\tid: string;\r\n\r\n\t/**\r\n\t *\r\n\t * Unit of measure id\r\n\t */\r\n\tunitOfMeasureId: string;\r\n\r\n\t/**\r\n\t * Base Unit of measure\r\n\t */\r\n\tunitOfMeasure: UnitOfMeasure;\r\n\r\n\t/**\r\n\t * The unit's of measure display name\r\n\t */\r\n\tlabel: string;\r\n\r\n\t/**\r\n\t * The unit's of measure quantity\r\n\t */\r\n\tquantity: number;\r\n\r\n\t/**\r\n\t * If this pricing line isn't available for purchase, this will contain a string-localizer-key explaining the reason why.\r\n\t */\r\n\tunavailabilityReason: string | undefined;\r\n} & MassPricingLineOptions;\r\n\r\ntype MassPricingLineOptions =\r\n\t| {\r\n\t\t\t/**\r\n\t\t\t * The unit's of measure weight unit\r\n\t\t\t */\r\n\t\t\tunitOfMass: UnitOfMass;\r\n\r\n\t\t\t/**\r\n\t\t\t * The unit's of measure weight\r\n\t\t\t */\r\n\t\t\tweight: number;\r\n\t }\r\n\t| {\r\n\t\t\tunitOfMass?: never;\r\n\t\t\tweight?: never;\r\n\t };\r\n\r\n/**\r\n * Represents state details pricing lines and pricing line selections for a product on a product details page.\r\n */\r\nexport interface ProductPricingLinesDetails {\r\n\t/**\r\n\t * The selected pricing lines\r\n\t */\r\n\tselected?: ProductPricingLine;\r\n\t/**\r\n\t * The array of available pricing lines\r\n\t */\r\n\tavailable: ProductPricingLine[];\r\n}\r\n\r\n/**\r\n * Reason that the exception was thrown when adding an item to the cart\r\n */\r\nexport enum AddToCartExceptionCode {\r\n\tgeneric = 'Generic',\r\n\tcartFull = 'CartFull',\r\n\tproductUnavailable = 'ProductUnavailable',\r\n\tproductOutOfStock = 'ProductOutOfStock',\r\n}\r\n\r\n/**\r\n * Interface used as request for getting bulk products partial data\r\n */\r\nexport interface BaseBulkPartialProductsDataOptions {\r\n\tproductIds: string[] | undefined;\r\n\tmissingKeys: Array;\r\n}\r\n","export class Request {\r\n\t/** This should correspond to the visitor id stored in the cookie for the user. */\r\n\tpublic visitorId?: string | null;\r\n\t/** This should correspond to the visit id stored in the cookie for the user. */\r\n\tpublic visitId?: string | null;\r\n\tpublic baseUrl?: string;\r\n\t/** This indicates whether preview has been enabled in the admin for that widget. */\r\n\tpublic enablePreview?: boolean;\r\n\t/** This should correspond to the Tracking Key for your engine. */\r\n\tpublic clientGuid?: string;\r\n\t/** If you are on a landing page that was set up in Hawksearch, this will be the corresponding landing page url of that page. */\r\n\tpublic landingPageUrl?: string;\r\n\t/** List of recommendations guids to return. */\r\n\tpublic widgetUids?: WidgetUid[];\r\n\t/** All information that is passed into the HawkSearch.Context object on page should be passed in here. */\r\n\tpublic contextProperties?: ContextDictionary;\r\n\t/** All information that is passed into HawkSearch.Context.Custom object on the page should be passed in here. */\r\n\tpublic customProperties?: ContextDictionary;\r\n\tpublic renderHTML?: boolean;\r\n}\r\n\r\nexport interface WidgetUid {\r\n\twidgetGuid?: string;\r\n\tuniqueId?: string;\r\n}\r\n\r\nexport class ContextDictionary {\r\n\tadd(key: string, value: unknown) {\r\n\t\tthis[key] = value;\r\n\t}\r\n\r\n\tclear() {\r\n\t\tfor (const key in this) {\r\n\t\t\tthis.remove(key);\r\n\t\t}\r\n\t}\r\n\r\n\tremove(key: string) {\r\n\t\tif (this.hasOwnProperty(key)) {\r\n\t\t\tdelete this[key];\r\n\t\t}\r\n\t}\r\n\r\n\tconstructor(state?: Record) {\r\n\t\tif (state === undefined) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tObject.entries(state).forEach(([key, value]) => {\r\n\t\t\tthis.add(key, value);\r\n\t\t});\r\n\t}\r\n}\r\n","export class Item {\r\n\tpublic brand: string;\r\n\tpublic price: string;\r\n\tpublic imageUrl: string;\r\n\tpublic isOnSale: boolean;\r\n\tpublic salePrice: string;\r\n\tpublic bestFragment: string | null;\r\n\tpublic color: string;\r\n\tpublic url: string;\r\n\tpublic id: string;\r\n\tpublic imageAlt: string;\r\n\tpublic imageOverAltTag: string | null;\r\n\tpublic imageOverUrl: string | null;\r\n\tpublic itemName: string;\r\n\tpublic maxPrice: string | null;\r\n\tpublic maxSalePrice: string | null;\r\n\tpublic minPrice: string | null;\r\n\tpublic minSalePrice: string | null;\r\n\tpublic postDate: string | null;\r\n\tpublic rating: string;\r\n\tpublic shortDescription: string | null;\r\n\tpublic sku: string | null;\r\n\tpublic itemIndex: number;\r\n\tpublic modelName: string;\r\n\tpublic modelType: string;\r\n\tpublic modelGuid: string;\r\n\tpublic customDict: Record;\r\n\tpublic constructor(init: Item) {\r\n\t\tObject.assign(this, init);\r\n\t}\r\n}\r\n","import { Item } from './Item';\r\n\r\nexport class Widget {\r\n\tpublic recommendationItems: Item[];\r\n\tpublic html: string;\r\n\tpublic widgetGuid: string;\r\n\tpublic widgetName: string;\r\n\tpublic widgeTitle: string;\r\n\tpublic widgetCssClass: string;\r\n\tpublic isCarousel: boolean;\r\n\tpublic carouselData: CarouselData;\r\n\tpublic isVertical: boolean;\r\n\tpublic itemsCount: number;\r\n\r\n\tpublic constructor(init: Widget) {\r\n\t\tObject.assign(this, init);\r\n\t\tthis.recommendationItems = init.recommendationItems.map((r) => new Item(r));\r\n\t}\r\n}\r\n\r\nexport class CarouselData {\r\n\tpublic showNextPrevButtons: boolean;\r\n\tpublic autoRotate: boolean;\r\n\tpublic autoRotateSpeed: number;\r\n\tpublic animationSpeed: number;\r\n\tpublic nofVisible: number;\r\n\tpublic isCircular: boolean;\r\n\tpublic scrollNumber: number;\r\n\tpublic showDots: boolean;\r\n\tpublic enableResponsive: boolean;\r\n\tpublic responseiveConfig: string;\r\n}\r\n","import { Widget } from './Widget';\r\n\r\nexport class Response {\r\n\t/** Indicates if request was successful. */\r\n\tpublic isSuccess: boolean;\r\n\tpublic requestId: string;\r\n\t/** Array of requested widgets. */\r\n\tpublic widgetItems?: Widget[];\r\n\r\n\tpublic constructor(init: Response) {\r\n\t\tObject.assign(this, init);\r\n\t\tthis.widgetItems = init.widgetItems?.map((r) => new Widget(r));\r\n\t}\r\n}\r\n","import { ContextDictionary } from 'shared/components/hawksearch/models/Recommendation';\r\n\r\n//#region Commerce\r\nexport function getHawkRecommendationContext(): ContextDictionary {\r\n\treturn new ContextDictionary(window.__ROC_HAWK_RECOMMENDATION_CONTEXT_OBJECT__);\r\n}\r\n//#endregion\r\n\r\nexport interface HawkRecommendation {\r\n\tContext: ContextDictionary;\r\n\tCustomContext: ContextDictionary;\r\n}\r\n\r\ndeclare global {\r\n\tinterface Window {\r\n\t\tHawkRecommendation: HawkRecommendation;\r\n\t\t__ROC_HAWK_RECOMMENDATION_CONTEXT_OBJECT__?: Record;\r\n\t}\r\n}\r\n\r\nconst Context = getHawkRecommendationContext();\r\nconst CustomContext = new ContextDictionary();\r\n\r\n// initialize HawkContext\r\nif (!window.HawkRecommendation) {\r\n\twindow.HawkRecommendation = {\r\n\t\tContext: Context,\r\n\t\tCustomContext: CustomContext,\r\n\t};\r\n}\r\n\r\nconst HawkRecommendation = window.HawkRecommendation;\r\n\r\nexport default {\r\n\tContext,\r\n\tCustomContext,\r\n};\r\n","import React from 'react';\r\n\r\nexport interface PlaceholderImageProps {\r\n\t/** Whether or not to display a spinner in the center of the placeholder. */\r\n\tshowSpinner: boolean;\r\n\tname: string;\r\n}\r\n\r\n/**\r\n * Renders placeholder image for hawksearch recommended product.\r\n */\r\nexport function PlaceholderImage({ showSpinner }: PlaceholderImageProps) {\r\n\treturn (\r\n\t\t
\r\n\t\t\t{showSpinner &&
Loading...
}\r\n\t\t
\r\n\t);\r\n}\r\n","import { Item as ItemModel } from 'models/Recommendation/Item';\r\nimport React, { useState } from 'react';\r\nimport { PlaceholderImage } from './PlaceholderImage';\r\n\r\nexport interface RecommendationImageProps {\r\n\titem: ItemModel;\r\n\tclassNameSuffix: string;\r\n}\r\n\r\n/**\r\n * Renders image for hawksearch recommended product.\r\n */\r\nexport function Image({ item }: RecommendationImageProps) {\r\n\tconst imageUrl: string = item.imageUrl;\r\n\tconst itemName: string = item.itemName;\r\n\tconst [hasImage, setHasImage] = useState(imageUrl !== '' && !!imageUrl);\r\n\tconst [imageLoaded, setImageLoaded] = useState(false);\r\n\r\n\treturn (\r\n\t\t<>\r\n\t\t\t{hasImage ? (\r\n\t\t\t\t
\r\n\t\t\t\t\t setImageLoaded(true)}\r\n\t\t\t\t\t\tonError={() => {\r\n\t\t\t\t\t\t\tsetHasImage(false);\r\n\t\t\t\t\t\t\tsetImageLoaded(false);\r\n\t\t\t\t\t\t}}\r\n\t\t\t\t\t\trole=\"presentation\"\r\n\t\t\t\t\t>\r\n\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t{`${itemName}`}\r\n\t\t\t\t\t\t
\r\n\t\t\t\t\t
\r\n\t\t\t\t\r\n\t\t\t) : null}\r\n\r\n\t\t\t{!imageLoaded ? (\r\n\t\t\t\t// if the main image hasn't loaded yet, show a placeholder\r\n\t\t\t\t
\r\n\t\t\t\t\t\r\n\t\t\t\t
\r\n\t\t\t) : null}\r\n\t\t\r\n\t);\r\n}\r\n","import { Item as ItemModel } from 'models/Recommendation/Item';\r\nimport React from 'react';\r\nimport { DisplayPrice } from 'shared-client/types/commerce/display-price';\r\nimport ProductPricing from 'shared/components/commerce/ProductPricing';\r\n\r\nexport interface ProductPriceRenderer {\r\n\titem: ItemModel;\r\n\tclassNameSuffix: string;\r\n}\r\n\r\n/**\r\n * Renders pricing for individual recommended product returned from hawk api using custom context.\r\n */\r\nexport function ProductPriceRenderer({ item }: ProductPriceRenderer) {\r\n\tconst displayPriceStringified =\r\n\t\titem.customDict['product_groupdisplayprice'] || item.customDict['product_displayprice'];\r\n\r\n\tlet displayPrice: DisplayPrice | undefined = undefined;\r\n\r\n\ttry {\r\n\t\tdisplayPrice = displayPriceStringified ? (JSON.parse(displayPriceStringified) as DisplayPrice) : undefined;\r\n\t} catch (error) {\r\n\t\tconsole.error('Unable to parse product price:', error);\r\n\t}\r\n\r\n\treturn ;\r\n}\r\n","import React from 'react';\r\n\r\nexport interface OptionalAnchorProps {\r\n\tchildren: React.ReactNode;\r\n\turl?: string;\r\n\tonClick?: () => void;\r\n}\r\n\r\nexport function OptionalAnchor({ url, children, onClick }: OptionalAnchorProps) {\r\n\treturn url ? (\r\n\t\t\r\n\t\t\t{children}\r\n\t\t\r\n\t) : (\r\n\t\t<>{children}\r\n\t);\r\n}\r\n","import React from 'react';\r\nimport { Image } from '../../Image';\r\nimport { ProductPriceRenderer } from './ProductPriceRenderer';\r\nimport { OptionalAnchor } from '../shared/OptionalAnchor';\r\nimport { ItemProps } from '../types';\r\n\r\n/**\r\n * Default rendering for an individual Hawk Recommendations item\r\n */\r\nexport function DefaultItem({ item, classNameSuffix, onClick }: ItemProps) {\r\n\treturn (\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t

\r\n\t\t\t\t\t{item.brand}\r\n\t\t\t\t\t{item.itemName}\r\n\t\t\t\t

\r\n\t\t\t\t\r\n\t\t\t
\r\n\t\t\r\n\t);\r\n}\r\n","import { DefaultItem } from 'features/hawk-recommendations/items/commerce/Item';\r\nimport React, { useEffect, useRef } from 'react';\r\nimport { Item as ItemModel } from 'shared/components/hawksearch/models/Recommendation/Item';\r\nimport Spinner from 'shared/components/Spinner';\r\nimport { useInViewOnce } from 'shared/hooks/useInViewOnce';\r\nimport { dispatchRocEvent } from 'shared/hooks/useRocEventHandler';\r\nimport type { TinySliderInstance, TinySliderSettings } from 'tiny-slider';\r\nimport uuid from 'uuid/v4';\r\nimport { getCustomWidgetItemComponent } from '../../items/strategy';\r\nimport { ItemProps, ItemStrategyProps } from '../../items/types';\r\nimport { WidgetProps } from '../types';\r\n\r\n/**\r\n * Renders a widget for the recommended products returned from hawk api.\r\n */\r\nexport function Carousel(props: WidgetProps) {\r\n\tconst { widgetData: widget, renderHTML, requestId, attributes } = props;\r\n\r\n\tconst currentInstanceId = useRef('hawk-recommendations-slider-' + uuid()).current;\r\n\tconst sliderRef = useRef(null);\r\n\r\n\tconst [ref, inView] = useInViewOnce({\r\n\t\tthreshold: 0,\r\n\t});\r\n\r\n\tconst tnsPromise = import('tiny-slider/src/tiny-slider').then((module) => module.tns);\r\n\r\n\t// bind tiny-slider on startup or resize\r\n\tconst initializeSlider = () => {\r\n\t\tif (sliderRef.current) {\r\n\t\t\tsliderRef.current.destroy();\r\n\t\t}\r\n\r\n\t\t(async () => {\r\n\t\t\tconst currentSliderDiv = document.getElementById(currentInstanceId);\r\n\t\t\tconst tns = await tnsPromise;\r\n\r\n\t\t\tconst getTinySliderInstance = () => {\r\n\t\t\t\tconst options: TinySliderSettings = {\r\n\t\t\t\t\tcontainer: `#${currentInstanceId}`,\r\n\t\t\t\t\titems: 1,\r\n\t\t\t\t\tslideBy: 'page',\r\n\t\t\t\t\tcontrols: false,\r\n\t\t\t\t\tmouseDrag: true,\r\n\t\t\t\t\tgutter: 15,\r\n\t\t\t\t\tlazyload: true,\r\n\t\t\t\t\tloop: false,\r\n\t\t\t\t\tresponsive: {\r\n\t\t\t\t\t\t768: {\r\n\t\t\t\t\t\t\titems: 2,\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\t1024: {\r\n\t\t\t\t\t\t\titems: 4,\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\t1200: {\r\n\t\t\t\t\t\t\titems: 5,\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t},\r\n\t\t\t\t};\r\n\r\n\t\t\t\treturn tns(options);\r\n\t\t\t};\r\n\r\n\t\t\tif (currentSliderDiv) {\r\n\t\t\t\tsliderRef.current = getTinySliderInstance();\r\n\t\t\t}\r\n\r\n\t\t\t// if there's a re-render, or possibly hmr, make sure to destroy the instance\r\n\t\t\t// to avoid memory leaks.\r\n\t\t\treturn () => {\r\n\t\t\t\tif (sliderRef.current) {\r\n\t\t\t\t\tsliderRef.current.destroy();\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t})();\r\n\t};\r\n\r\n\t// Bind tiny-slider on startup\r\n\tuseEffect(() => {\r\n\t\tinitializeSlider();\r\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\r\n\t}, [inView]);\r\n\r\n\tif (!inView) {\r\n\t\treturn
;\r\n\t}\r\n\r\n\tif (renderHTML && widget.html) {\r\n\t\treturn
;\r\n\t}\r\n\r\n\tif (widget.recommendationItems.length == 0) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\t// function for dispatching hawk-recommendation-click event\r\n\t// this is handled by hawksearch-commerce-tracker to report click event to Hawk Tracking API\r\n\tconst dispatchWidgetClickEvent = (item: ItemModel, widgetGuid: string) => {\r\n\t\tif (item.id) {\r\n\t\t\tdispatchRocEvent('hawk-recommendation-click', {\r\n\t\t\t\titemIndex: item.itemIndex,\r\n\t\t\t\trequestId: requestId,\r\n\t\t\t\tuniqueId: item.id,\r\n\t\t\t\twidgetGuid: widgetGuid,\r\n\t\t\t});\r\n\t\t}\r\n\t};\r\n\r\n\treturn (\r\n\t\t}>\r\n\t\t\t

\r\n\t\t\t
\r\n\t\t\t\t
\r\n\t\t\t\t\t{widget.recommendationItems.map((item, key) => {\r\n\t\t\t\t\t\tconst ItemComponent = getWidgetItemComponent({\r\n\t\t\t\t\t\t\twidgetGuid: widget.widgetGuid,\r\n\t\t\t\t\t\t\titem,\r\n\t\t\t\t\t\t\tattributes,\r\n\t\t\t\t\t\t\twidgetComponentType: Carousel,\r\n\t\t\t\t\t\t});\r\n\r\n\t\t\t\t\t\treturn (\r\n\t\t\t\t\t\t\t dispatchWidgetClickEvent(item, widget.widgetGuid)}\r\n\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t})}\r\n\t\t\t\t
\r\n\t\t\t
\r\n\t\t\r\n\t);\r\n}\r\n\r\n/**\r\n * This is the default strategy for picking out an item type. It only checks if a custom one has been defined,\r\n * and if that returns anything, that component is returned. Otherwise, we just return the default component.\r\n * If you need to customize this, change `getCustomWidgetItemComponent`\r\n */\r\nfunction getWidgetItemComponent(props: ItemStrategyProps): React.ComponentType {\r\n\tconst customComponent = getCustomWidgetItemComponent(props);\r\n\r\n\tif (customComponent !== undefined) {\r\n\t\treturn customComponent;\r\n\t}\r\n\r\n\treturn DefaultItem;\r\n}\r\n","import axios, { CancelToken } from 'axios';\r\nimport { getInitialProductDetailsState } from 'features/commerce/product-details/types';\r\nimport RocHawkConfig from 'features/search/RocHawkConfig';\r\nimport {\r\n\tHawksearchAttributes,\r\n\tselectionsToHawkAttributes,\r\n} from 'features/tracking/trackers/commerce/hawksearch/hawk-search-commerce-tracker';\r\nimport { ContextDictionary, WidgetUid } from 'models/Recommendation/Request';\r\nimport { Response as RecommendationResponse } from 'models/Recommendation/Response';\r\nimport HawkClient from 'net/HawkClient';\r\nimport React, { useEffect, useState } from 'react';\r\nimport ReactDOM from 'react-dom';\r\nimport AxiosHelper from 'services/AxiosHelper';\r\nimport {\r\n\tcreateGuid,\r\n\tgetCookie,\r\n\tgetVisitExpiry,\r\n\tgetVisitorExpiry,\r\n\tsetCookie,\r\n} from 'shared/components/hawksearch/helpers/Cookies';\r\nimport HawkRecommendation from 'shared/components/hawksearch/helpers/hawkRecommendationContext';\r\nimport { Widget } from 'shared/components/hawksearch/models/Recommendation/Widget';\r\nimport Spinner from 'shared/components/Spinner';\r\nimport useRocEventHandler, { dispatchRocEvent } from 'shared/hooks/useRocEventHandler';\r\nimport { Carousel } from './widgets/commerce/Carousel';\r\nimport { getCustomWidgetComponent } from './widgets/strategy';\r\nimport { WidgetProps, WidgetStrategyProps } from './widgets/types';\r\n\r\nconst initialProductState = getInitialProductDetailsState();\r\n\r\n/**\r\n * Main loader component responsible for initializing portals to all elements on the page with widget guids\r\n * Also handles all data loading, to make sure we send all requests to the server in bulk, allowing hawk\r\n * to dedupe the results for us.\r\n */\r\nexport function Loader() {\r\n\tconst config = RocHawkConfig;\r\n\tconst client: HawkClient = new HawkClient(config);\r\n\tconst renderHTML: boolean = false;\r\n\tconst [recommendations, setRecommendations] = useState(null);\r\n\tconst [loading, setLoading] = useState(true);\r\n\t//#region Commerce\r\n\tconst [hawkAttributes, setHawkAttributes] = useState(selectionsToHawkAttributes(initialProductState.selections));\r\n\t//#endregion\r\n\r\n\tuseEffect(() => {\r\n\t\tconst cts = axios.CancelToken.source();\r\n\r\n\t\t(async () => {\r\n\t\t\tawait getRecommendations(hawkAttributes, cts.token);\r\n\t\t})();\r\n\r\n\t\treturn () => {\r\n\t\t\tcts.cancel();\r\n\t\t};\r\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\r\n\t}, [hawkAttributes]);\r\n\r\n\t//#region Commerce\r\n\tuseRocEventHandler(\r\n\t\t'product-selection-updated',\r\n\t\t({ product }) => {\r\n\t\t\tconst newHawkAttributes = selectionsToHawkAttributes(product.productDetails?.selections);\r\n\t\t\tsetHawkAttributes(newHawkAttributes);\r\n\t\t},\r\n\t\t[],\r\n\t);\r\n\t//#endregion\r\n\r\n\t/**\r\n\t * Performs an recommendation request to the Hawk API and populates the recommendation widgets set of this component.\r\n\t */\r\n\tasync function getRecommendations(hawkAttributes?: HawksearchAttributes[], cancellationToken?: CancelToken) {\r\n\t\tconst widgetUids = getRecommendationPlaceholders();\r\n\r\n\t\tif (!widgetUids || widgetUids.length === 0) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tlet recommendationResults: RecommendationResponse | null = null;\r\n\t\tlet visitorId: string | null = getCookie('hawk_visit_id');\r\n\t\tlet visitId: string | null = getCookie('hawk_visitor_id');\r\n\r\n\t\tconst isNewVisitor = !visitId || !visitorId;\r\n\r\n\t\tif (!visitId) {\r\n\t\t\tsetCookie('hawk_visit_id', createGuid(), getVisitExpiry());\r\n\t\t\tvisitId = getCookie('hawk_visit_id');\r\n\t\t}\r\n\r\n\t\tif (!visitorId) {\r\n\t\t\tsetCookie('hawk_visitor_id', createGuid(), getVisitorExpiry());\r\n\t\t\tvisitorId = getCookie('hawk_visitor_id');\r\n\t\t}\r\n\r\n\t\tif (isNewVisitor) {\r\n\t\t\tAxiosHelper.post('/ajax/hawksearch/identify', {\r\n\t\t\t\tvisitId: visitId,\r\n\t\t\t\tvisitorId: visitorId,\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tlet contextProperties = new ContextDictionary();\r\n\t\tlet customProperties = new ContextDictionary();\r\n\r\n\t\tif (window.HawkRecommendation) {\r\n\t\t\tcontextProperties = HawkRecommendation.Context;\r\n\t\t\tcustomProperties = HawkRecommendation.CustomContext;\r\n\t\t}\r\n\r\n\t\t//#region Commerce\r\n\t\t// add all selections to the hawk context.\r\n\t\thawkAttributes?.map((attribute) => {\r\n\t\t\tif (attribute.value) {\r\n\t\t\t\tcontextProperties.add(`${attribute.name}`, attribute.value);\r\n\t\t\t} else {\r\n\t\t\t\tcontextProperties.remove(attribute.name);\r\n\t\t\t}\r\n\t\t});\r\n\t\t//#endregion\r\n\r\n\t\ttry {\r\n\t\t\trecommendationResults = await client.getRecommendationWidgetItems(\r\n\t\t\t\t{\r\n\t\t\t\t\tvisitId,\r\n\t\t\t\t\tvisitorId,\r\n\t\t\t\t\twidgetUids: widgetUids,\r\n\t\t\t\t\tclientGuid: config.clientGuid,\r\n\t\t\t\t\tenablePreview: config.isInPreview,\r\n\t\t\t\t\trenderHTML,\r\n\t\t\t\t\tcontextProperties,\r\n\t\t\t\t\tcustomProperties,\r\n\t\t\t\t},\r\n\t\t\t\tcancellationToken,\r\n\t\t\t);\r\n\r\n\t\t\t// trigger event for widget visibility based on how many items are included\r\n\t\t\t// by default, this is used to show/hide tabs on the pdp\r\n\t\t\twidgetUids.forEach((w) => {\r\n\t\t\t\tif (!w.widgetGuid) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst matchedResult = recommendationResults?.widgetItems?.find((f) => f.widgetGuid === w.widgetGuid);\r\n\r\n\t\t\t\tdispatchRocEvent('hawk-recs-widget-loaded', {\r\n\t\t\t\t\twidgetGuid: w.widgetGuid,\r\n\t\t\t\t\thasItems: matchedResult ? matchedResult.recommendationItems.length > 0 : false,\r\n\t\t\t\t});\r\n\t\t\t});\r\n\t\t} catch (error) {\r\n\t\t\tif (axios.isCancel(error)) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tconsole.error('Recommendation widget request error:', error);\r\n\r\n\t\t\t// if something goes wrong and we can't load recs, then send events to hide all\r\n\t\t\t// each event handler component is given the choice to care about this or not.\r\n\t\t\twidgetUids.forEach((w) => {\r\n\t\t\t\tif (!w.widgetGuid) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tdispatchRocEvent('hawk-recs-widget-loaded', {\r\n\t\t\t\t\twidgetGuid: w.widgetGuid,\r\n\t\t\t\t\thasItems: false,\r\n\t\t\t\t});\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tsetLoading(false);\r\n\r\n\t\tif (recommendationResults) {\r\n\t\t\tif (!recommendationResults.isSuccess) {\r\n\t\t\t\tconsole.error('Recommendation result error:', recommendationResults);\r\n\t\t\t\tsetRecommendations(null);\r\n\t\t\t} else {\r\n\t\t\t\tsetRecommendations(new RecommendationResponse(recommendationResults));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (!recommendations || !recommendations.widgetItems || recommendations.widgetItems.length === 0) {\r\n\t\t// nothing to render\r\n\t\treturn null;\r\n\t}\r\n\r\n\treturn (\r\n\t\t}>\r\n\t\t\t{recommendations.widgetItems.map((widget, index) => {\r\n\t\t\t\tconst targetElements = document.querySelectorAll(`[data-widgetguid='${widget.widgetGuid}']`);\r\n\r\n\t\t\t\tif (targetElements.length === 0) {\r\n\t\t\t\t\tconsole.error(`No matching hawk recommendation widget was found in the DOM (${widget.widgetGuid})`);\r\n\r\n\t\t\t\t\treturn null;\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn (\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t{Array.from(targetElements).map((el, index) => (\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t))}\r\n\t\t\t\t\t\r\n\t\t\t\t);\r\n\t\t\t})}\r\n\t\t\r\n\t);\r\n}\r\n\r\ninterface WidgetContainerProps {\r\n\telement: Element;\r\n\tattributes: NamedNodeMap;\r\n\tloading: boolean;\r\n\twidget: Widget;\r\n\trenderHtml?: boolean;\r\n\trequestId: string;\r\n}\r\n\r\n/**\r\n * Adds a layer to easily return portals to multiple components as this cannot be done from a single component.\r\n */\r\nfunction WidgetContainer({\r\n\twidget,\r\n\tloading,\r\n\trenderHtml = false,\r\n\trequestId,\r\n\telement,\r\n\tattributes,\r\n}: WidgetContainerProps) {\r\n\tconst WidgetComponent = getWidgetComponent({\r\n\t\twidgetGuid: widget.widgetGuid,\r\n\t\tattributes,\r\n\t});\r\n\r\n\treturn ReactDOM.createPortal(\r\n\t\t,\r\n\t\telement,\r\n\t);\r\n}\r\n\r\n/**\r\n * This is the default strategy for picking out a widget type. It only checks if a custom one has been defined,\r\n * and if that returns anything, that component is returned. Otherwise, we just return the default component.\r\n * If you need to customize this, change `getCustomWidgetComponent`\r\n */\r\nfunction getWidgetComponent(props: WidgetStrategyProps): React.ComponentType {\r\n\tconst customComponent = getCustomWidgetComponent(props);\r\n\r\n\tif (customComponent !== undefined) {\r\n\t\treturn customComponent;\r\n\t}\r\n\r\n\treturn Carousel;\r\n}\r\n\r\n/**\r\n * Grabs all requested WidgetUids based on the elements on the page.\r\n * The elements match up exactly to what Hawk provides in their admin.\r\n */\r\nfunction getRecommendationPlaceholders() {\r\n\tconst widgetUids: WidgetUid[] = [];\r\n\r\n\tdocument.querySelectorAll('[data-widgetguid]').forEach(function (element) {\r\n\t\tconst guid = element.getAttribute('data-widgetguid');\r\n\t\tif (guid) {\r\n\t\t\twidgetUids.push({\r\n\t\t\t\twidgetGuid: guid,\r\n\t\t\t});\r\n\t\t}\r\n\t});\r\n\r\n\treturn widgetUids;\r\n}\r\n","import React from 'react';\r\nimport { initReactApp } from 'shared/util/ApplicationInit';\r\nimport { Loader } from './Loader';\r\n\r\nconst render = initReactApp(() => , 'hawk-recommendations');\r\n\r\nrender();\r\n\r\n// optional, use this to enable hot reloading\r\nif ((module as any).hot) {\r\n\t(module as any).hot.accept('./Loader', () => {\r\n\t\trender();\r\n\t});\r\n}\r\n"],"sourceRoot":""}