@envive-ai/react-hooks 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +2 -0
- package/README.md +2 -0
- package/dist/GridInsertionService-CEYo9pGj.js +22 -0
- package/dist/GridInsertionService-CS_bnPh0.cjs +28 -0
- package/dist/bandolier-Ble8jEa8.js +1221 -0
- package/dist/bandolier-Bm2xAt_j.cjs +1221 -0
- package/dist/carpe-Da7b-LCW.cjs +599 -0
- package/dist/carpe-W13mhRRP.js +597 -0
- package/dist/cdnService-CZ-aXcY6.cjs +23 -0
- package/dist/cdnService-zQfKk3Eb.js +18 -0
- package/dist/chatElementDisplayLocation-CX8fuNao.d.cts +239 -0
- package/dist/chatElementDisplayLocation-CwptS9tx.d.ts +239 -0
- package/dist/chunk-CUT6urMc.cjs +30 -0
- package/dist/contexts/index.cjs +13 -0
- package/dist/contexts/index.d.cts +65 -0
- package/dist/contexts/index.d.ts +66 -0
- package/dist/contexts/index.js +7 -0
- package/dist/contexts-BRjfVq_k.js +5064 -0
- package/dist/contexts-BYArqZtK.cjs +5164 -0
- package/dist/coterie-3y0D9ko4.cjs +229 -0
- package/dist/coterie-DOWcJAYv.js +229 -0
- package/dist/custservice-types-CFIFwZ-r.js +10 -0
- package/dist/custservice-types-CkfxZiHY.cjs +16 -0
- package/dist/default-C2fEZKXk.js +175 -0
- package/dist/default-CBUq6Q6G.cjs +4 -0
- package/dist/default-CGIFZK6m.js +4 -0
- package/dist/default-D_KPZdPJ.cjs +198 -0
- package/dist/divIds-Bss-btao.js +49 -0
- package/dist/divIds-DnZNd7rA.cjs +223 -0
- package/dist/dreamlandBaby-DCIsuU9R.cjs +338 -0
- package/dist/dreamlandBaby-DvSaZGrz.js +338 -0
- package/dist/entrypoints-D_JUvkgy.cjs +18 -0
- package/dist/entrypoints-YLQsbBRD.js +6 -0
- package/dist/enviveConfigContext-CUGLpPGU.js +34 -0
- package/dist/enviveConfigContext-Dfr2VH6u.cjs +48 -0
- package/dist/fiveCbd-B1SESMCO.js +605 -0
- package/dist/fiveCbd-CkOlVby_.cjs +605 -0
- package/dist/forLoveAndLemons-CfYPMnKS.cjs +660 -0
- package/dist/forLoveAndLemons-DmwYZIk0.js +658 -0
- package/dist/greenpan-Bsl3ir59.cjs +389 -0
- package/dist/greenpan-BtOi45lf.js +389 -0
- package/dist/grooveLife-6_dtYsRk.js +334 -0
- package/dist/grooveLife-Cmm1PSCL.cjs +334 -0
- package/dist/homegrownCannabis-C-kw-74X.js +400 -0
- package/dist/homegrownCannabis-CO0uY_mp.cjs +400 -0
- package/dist/hooks/index.cjs +16 -0
- package/dist/hooks/index.d.cts +357 -0
- package/dist/hooks/index.d.ts +357 -0
- package/dist/hooks/index.js +7 -0
- package/dist/jackArcher-CLVmwwpI.js +719 -0
- package/dist/jackArcher-DdYTIzAV.cjs +719 -0
- package/dist/jordanCraig-Am-Oor-O.js +1778 -0
- package/dist/jordanCraig-_u3-w4Hp.cjs +1778 -0
- package/dist/kindredBravely-CWovIDSc.cjs +482 -0
- package/dist/kindredBravely-eWp-ud_E.js +482 -0
- package/dist/kutFromTheKloth-BMV4BuGQ.js +361 -0
- package/dist/kutFromTheKloth-Q589bAOC.cjs +361 -0
- package/dist/larryAndSerges-BMUlTgI-.js +252 -0
- package/dist/larryAndSerges-CEau764j.cjs +252 -0
- package/dist/leapsAndRebounds-DGMzPO7T.js +352 -0
- package/dist/leapsAndRebounds-DHAtRTJD.cjs +352 -0
- package/dist/logger-Dln20ans.cjs +25 -0
- package/dist/logger-pdEEY8T2.js +19 -0
- package/dist/longevityrx-CZW8Hxzi.cjs +312 -0
- package/dist/longevityrx-jH2JLhNH.js +312 -0
- package/dist/lookOptic-BGXP5P_V.js +274 -0
- package/dist/lookOptic-CA6RwLbG.cjs +274 -0
- package/dist/mantraBrand-Cm9_PBCT.js +742 -0
- package/dist/mantraBrand-DByNqpnL.cjs +742 -0
- package/dist/medterra-B0wxj_PV.js +575 -0
- package/dist/medterra-DnPN2ksU.cjs +575 -0
- package/dist/modells-Bmz8Ag5M.js +476 -0
- package/dist/modells-CoYgkLSp.cjs +476 -0
- package/dist/models-DHdb7QWn.js +51 -0
- package/dist/models-ixxUsGL_.cjs +69 -0
- package/dist/pressedFloral-DSKs_oVG.js +653 -0
- package/dist/pressedFloral-DjBiSoUl.cjs +653 -0
- package/dist/skinPerfection-B_3xzVNS.cjs +326 -0
- package/dist/skinPerfection-IDrBuAPt.js +326 -0
- package/dist/snapSupplements-BJk5T5ba.js +277 -0
- package/dist/snapSupplements-BStTsdOZ.cjs +277 -0
- package/dist/socialProofClasses-Bhv2Vulz.js +9 -0
- package/dist/socialProofClasses-CrQBWdSA.cjs +39 -0
- package/dist/spanx-BYg0LE7R.js +653 -0
- package/dist/spanx-LwU1zSzq.cjs +655 -0
- package/dist/spanxStaging-CfSmuKYB.js +837 -0
- package/dist/spanxStaging-OZLV9qix.cjs +840 -0
- package/dist/suggestionBarV2-types-BllzwsBD.js +34 -0
- package/dist/suggestionBarV2-types-CaovchMP.cjs +46 -0
- package/dist/supergoop-BqPXDnKk.cjs +327 -0
- package/dist/supergoop-CIlrHND_.js +325 -0
- package/dist/types-C4T5UOIW.cjs +230 -0
- package/dist/types-CYNvLeSA.js +176 -0
- package/dist/uniqueVintage-B30mOqbH.cjs +1205 -0
- package/dist/uniqueVintage-CFueJOhO.js +1203 -0
- package/dist/venaCbd-DHGZy49P.cjs +357 -0
- package/dist/venaCbd-T0CqVD4k.js +357 -0
- package/dist/westonJonBoucher-BdMzs_Yg.cjs +414 -0
- package/dist/westonJonBoucher-b4TCQ4ev.js +414 -0
- package/dist/wineEnthusiast-BLGlOjgr.cjs +932 -0
- package/dist/wineEnthusiast-BqR0i_54.js +932 -0
- package/dist/wolfMattress-CyyO-LoC.js +362 -0
- package/dist/wolfMattress-DNGZOivg.cjs +362 -0
- package/dist/wolfTactical-3Mm2fvVF.js +341 -0
- package/dist/wolfTactical-BmXYlFjr.cjs +341 -0
- package/package.json +66 -0
- package/src/adapters/amplitude/amplitudeAdapter.ts +454 -0
- package/src/adapters/amplitude/index.ts +2 -0
- package/src/adapters/amplitude/stubAmplitudeAdapter.ts +34 -0
- package/src/adapters/spiffy/commerce/api.ts +596 -0
- package/src/adapters/spiffy/commerce/exceptions/sessionExceptions.ts +6 -0
- package/src/adapters/spiffy/commerce/exceptions/unsupportedProductExceptions.ts +6 -0
- package/src/adapters/spiffy/commerce/graphql.ts +184 -0
- package/src/application/config/generalStaticConfig.ts +37 -0
- package/src/application/logging/logger.ts +29 -0
- package/src/application/models/api/context.ts +4 -0
- package/src/application/models/api/generationParams.ts +4 -0
- package/src/application/models/api/nextMessageRequest.ts +11 -0
- package/src/application/models/api/orgAnalyticsConfig.ts +19 -0
- package/src/application/models/api/orgConfigResults.ts +40 -0
- package/src/application/models/api/organizationConfig.ts +12 -0
- package/src/application/models/api/response.ts +132 -0
- package/src/application/models/api/responseGenerics.ts +67 -0
- package/src/application/models/api/search.ts +26 -0
- package/src/application/models/api/suggestion.ts +4 -0
- package/src/application/models/api/supportedEventRequest.ts +8 -0
- package/src/application/models/api/userEvent.ts +101 -0
- package/src/application/models/cachedValue.ts +8 -0
- package/src/application/models/chatElementDisplayLocation.ts +22 -0
- package/src/application/models/clientDetails.ts +18 -0
- package/src/application/models/colorsConfig.ts +28 -0
- package/src/application/models/conversationalSearchIds.ts +5 -0
- package/src/application/models/dataLayer.ts +45 -0
- package/src/application/models/domMutationContinuation.ts +7 -0
- package/src/application/models/domObservationStrategy.ts +9 -0
- package/src/application/models/events.ts +5 -0
- package/src/application/models/featureGates.ts +23 -0
- package/src/application/models/frontendConfig.ts +14 -0
- package/src/application/models/googleAnalyticsEvents.ts +8 -0
- package/src/application/models/graphql/index.ts +2 -0
- package/src/application/models/graphql/queries/getMerchantColorsQuery.ts +37 -0
- package/src/application/models/graphql/queries/getMerchantFrontendConfigQuery.ts +103 -0
- package/src/application/models/graphql/queries/getMerchantOrgIdQuery.ts +11 -0
- package/src/application/models/guards/api/index.ts +12 -0
- package/src/application/models/guards/api/isApiFormResponse.ts +90 -0
- package/src/application/models/guards/api/isApiFormSubmittedResponseAttributes.ts +37 -0
- package/src/application/models/guards/api/isApiOrderResponseAttributes.ts +155 -0
- package/src/application/models/guards/api/isApiOrgConfigResults.ts +277 -0
- package/src/application/models/guards/api/isApiOrganizationConfig.ts +207 -0
- package/src/application/models/guards/api/isApiPDPEventAttributes.ts +21 -0
- package/src/application/models/guards/api/isApiPLPEventAttributes.ts +41 -0
- package/src/application/models/guards/api/isApiPageResponseAttributes.ts +21 -0
- package/src/application/models/guards/api/isApiProductResponseAttributes.ts +85 -0
- package/src/application/models/guards/api/isApiProductSearchAttributes.ts +23 -0
- package/src/application/models/guards/api/isApiProductSearchFilterAttributes.ts +15 -0
- package/src/application/models/guards/api/isApiQueryTypedEventAttributes.ts +4 -0
- package/src/application/models/guards/api/isApiResponse.ts +39 -0
- package/src/application/models/guards/api/isApiReviewResponseAttributes.ts +30 -0
- package/src/application/models/guards/api/isApiReviewRichInformation.ts +37 -0
- package/src/application/models/guards/api/isApiSearchEventAttributes.ts +28 -0
- package/src/application/models/guards/api/isApiSuggestion.ts +36 -0
- package/src/application/models/guards/api/isApiSuggestionClickedEventAttributes.ts +9 -0
- package/src/application/models/guards/api/isApiTextResponseAttributes.ts +9 -0
- package/src/application/models/guards/api/isApiUserEvent.ts +25 -0
- package/src/application/models/guards/graphQL/isGraphQLColorsConfig.ts +50 -0
- package/src/application/models/guards/isBaseEcommerceEvent.ts +17 -0
- package/src/application/models/guards/isGA4EcommerceEvent.ts +17 -0
- package/src/application/models/guards/isLegacyUAEcommerceEvent.ts +17 -0
- package/src/application/models/guards/isMobilePLPChatPlacementParameter.ts +11 -0
- package/src/application/models/guards/isSpanxTakeAQuizCtaParameter.ts +4 -0
- package/src/application/models/guards/isVariantInfo.ts +37 -0
- package/src/application/models/guards/utils.ts +43 -0
- package/src/application/models/index.ts +20 -0
- package/src/application/models/localStorageEventListener.ts +4 -0
- package/src/application/models/message.ts +146 -0
- package/src/application/models/mobilePLPChatPlacementParameter.ts +3 -0
- package/src/application/models/orgsEnum.ts +36 -0
- package/src/application/models/productExperiment.ts +5 -0
- package/src/application/models/spanxTakeAQuizCtaParameter.ts +4 -0
- package/src/application/models/spiffyWidgets.ts +16 -0
- package/src/application/models/supportedOrgs.ts +137 -0
- package/src/application/models/utilityTypes/camelCase.ts +87 -0
- package/src/application/models/utilityTypes/camelCasedPropertiesDeep.ts +80 -0
- package/src/application/models/utilityTypes/delimiterCase.ts +121 -0
- package/src/application/models/utilityTypes/delimiterCasedPropertiesDeep.ts +98 -0
- package/src/application/models/utilityTypes/index.ts +1 -0
- package/src/application/models/utilityTypes/internal.ts +93 -0
- package/src/application/models/utilityTypes/primitive.ts +8 -0
- package/src/application/models/utilityTypes/snakeCasedPropertiesDeep.ts +49 -0
- package/src/application/models/utilityTypes/splitWords.ts +76 -0
- package/src/application/models/utilityTypes/trim.ts +28 -0
- package/src/application/models/utilityTypes/unknownArray.ts +25 -0
- package/src/application/models/utils/snakeToCamelTransformer.ts +90 -0
- package/src/application/models/utils/stringToFulfillmentDisplayStatusEnumValue.ts +68 -0
- package/src/application/models/validators/validateGraphQLColorsConfig.ts +29 -0
- package/src/application/models/validators/validateGraphQLFrontendConfig.ts +594 -0
- package/src/application/models/validators/validateGraphQLOrgId.ts +7 -0
- package/src/application/models/validators/validateMobilePLPChatPlacementParameter.ts +14 -0
- package/src/application/models/validators/validateOrgConfigResults.ts +47 -0
- package/src/application/models/validators/validateOrganizationConfig.ts +37 -0
- package/src/application/models/validators/validateResponse.ts +187 -0
- package/src/application/models/validators/validateSuggestion.ts +16 -0
- package/src/application/models/validators/validateUserEvent.ts +110 -0
- package/src/application/models/variantInfo/index.ts +1 -0
- package/src/application/models/variantInfo/pageVisitInfo.ts +6 -0
- package/src/application/models/variantInfo/plpInfo.ts +3 -0
- package/src/application/models/variantInfo/productInfo.ts +5 -0
- package/src/application/models/variantInfo/variantInfo.ts +23 -0
- package/src/application/service/cachingService.ts +84 -0
- package/src/application/service/cdnService.ts +18 -0
- package/src/application/service/customerService/index.ts +8 -0
- package/src/application/service/customerService/providers/UnsupportedCustomerService.ts +15 -0
- package/src/application/service/customerService/types.ts +31 -0
- package/src/application/service/domMutationObserver.ts +320 -0
- package/src/application/service/domMutations/GridInsertionService.ts +123 -0
- package/src/application/service/domMutations/dataLayer/dataLayerEventsListener.ts +99 -0
- package/src/application/service/domMutations/domInsertionService.ts +90 -0
- package/src/application/service/domMutations/domMutationListener.ts +15 -0
- package/src/application/service/domMutations/domMutationListenerState.ts +52 -0
- package/src/application/service/domMutations/floatingChat/embeddedChatsPlacementsListener.ts +41 -0
- package/src/application/service/domMutations/gladly/gladlyListener.ts +61 -0
- package/src/application/service/domMutations/spiffy/orgs/common/kustomerVisibilityListener.ts +41 -0
- package/src/application/service/domMutations/spiffy/orgs/common/orgsCommonDataLayerListener.ts +119 -0
- package/src/application/service/environmentService.ts +51 -0
- package/src/application/service/featureFlagService.ts +130 -0
- package/src/application/service/kustomerIntegrationService.ts +111 -0
- package/src/application/service/localStorageService.ts +77 -0
- package/src/application/service/pageVariantService.ts +779 -0
- package/src/application/service/searchService.ts +140 -0
- package/src/application/service/sessionStorageService.ts +27 -0
- package/src/application/service/shopifyUrlService.ts +63 -0
- package/src/application/service/userIdentityService.ts +114 -0
- package/src/application/service/windowChatToggleService.ts +71 -0
- package/src/application/service/windowDataLayerService.ts +181 -0
- package/src/application/service/windowFrontendConfigService.ts +104 -0
- package/src/application/utils/__tests__/divideArrays.test.ts +14 -0
- package/src/application/utils/analyticsUtils.ts +110 -0
- package/src/application/utils/coreContextToApiContext.ts +11 -0
- package/src/application/utils/coreUserEventToApiUserEvent.ts +106 -0
- package/src/application/utils/divideArray.ts +7 -0
- package/src/application/utils/domObserver.ts +96 -0
- package/src/application/utils/elementObserver.ts +246 -0
- package/src/application/utils/imageFilter.ts +12 -0
- package/src/application/utils/index.ts +3 -0
- package/src/application/utils/merchantUtils.ts +16 -0
- package/src/application/utils/messageFromFormSubmittedEvent.ts +31 -0
- package/src/application/utils/messageFromQueryEvent.ts +38 -0
- package/src/application/utils/messageFromResponse.ts +133 -0
- package/src/application/utils/messageFromSuggestionEvent.ts +32 -0
- package/src/application/utils/mouseEventTypes.ts +1 -0
- package/src/application/utils/mutationHelper.ts +51 -0
- package/src/application/utils/nextMessageRequestToApiRequest.ts +31 -0
- package/src/application/utils/nodeSelector.ts +133 -0
- package/src/application/utils/overrides.ts +196 -0
- package/src/application/utils/stringUtils.ts +55 -0
- package/src/application/utils/supportedEventRequestToApiRequest.ts +12 -0
- package/src/application/utils/urlsParser.ts +53 -0
- package/src/application/utils/validation.ts +5 -0
- package/src/atoms/app/index.ts +57 -0
- package/src/atoms/app/variant.ts +261 -0
- package/src/atoms/atomStore.ts +34 -0
- package/src/atoms/chat/chatState.ts +44 -0
- package/src/atoms/chat/form.ts +19 -0
- package/src/atoms/chat/index.ts +38 -0
- package/src/atoms/chat/lastMessage.ts +11 -0
- package/src/atoms/chat/messageQueue.ts +65 -0
- package/src/atoms/chat/performanceMetrics.ts +84 -0
- package/src/atoms/chat/renderedWidgetRefs.ts +28 -0
- package/src/atoms/chat/replies.ts +51 -0
- package/src/atoms/chat/suggestions.ts +36 -0
- package/src/atoms/globalSearch.ts +12 -0
- package/src/atoms/index.ts +5 -0
- package/src/atoms/org/customerService.ts +13 -0
- package/src/atoms/org/graphqlConfig.ts +27 -0
- package/src/atoms/org/index.ts +7 -0
- package/src/atoms/org/merchantCss.ts +44 -0
- package/src/atoms/org/org.ts +256 -0
- package/src/atoms/org/orgAnalyticsConfig.ts +28 -0
- package/src/atoms/org/orgPageConfig.ts +38 -0
- package/src/atoms/org/orgUIConfig.ts +122 -0
- package/src/atoms/search/chatSearch.ts +293 -0
- package/src/atoms/search/index.ts +2 -0
- package/src/atoms/search/productFilters.ts +207 -0
- package/src/atoms/search/productSorter.ts +23 -0
- package/src/atoms/search/searchAPI.ts +194 -0
- package/src/atoms/search/types.ts +55 -0
- package/src/atoms/search/utils.ts +18 -0
- package/src/config/divIds.ts +27 -0
- package/src/config/locators/components/chat/entrypoints.ts +13 -0
- package/src/config/locators/components/chat/index.ts +23 -0
- package/src/config/locators/components/chat/preview.ts +13 -0
- package/src/config/locators/components/chat/variants/index.ts +16 -0
- package/src/config/locators/components/common/buttons.ts +6 -0
- package/src/config/locators/components/common/cards.ts +18 -0
- package/src/config/locators/components/common/links.ts +1 -0
- package/src/config/locators/components/common/tables.ts +2 -0
- package/src/config/locators/components/floating-button.ts +2 -0
- package/src/config/locators/components/index.ts +3 -0
- package/src/config/locators/components/report-issue.ts +21 -0
- package/src/config/locators/components/search/index.ts +5 -0
- package/src/config/locators/components/shadow-dom.ts +1 -0
- package/src/config/locators/embedded.ts +21 -0
- package/src/config/locators/index.ts +3 -0
- package/src/config/socialProofClasses.ts +17 -0
- package/src/contexts/chatContext.tsx +451 -0
- package/src/contexts/enviveConfigContext.tsx +70 -0
- package/src/contexts/index.ts +4 -0
- package/src/contexts/systemSettingsContext.tsx +61 -0
- package/src/contexts/types.ts +1059 -0
- package/src/enabled-features.ts +83 -0
- package/src/events/event-types.ts +11 -0
- package/src/events/index.ts +52 -0
- package/src/events/registerAnalyticsListeners.ts +49 -0
- package/src/extension.ts +63 -0
- package/src/hooks/index.ts +22 -0
- package/src/hooks/useBlockBackButton.ts +29 -0
- package/src/hooks/useChatToggle.ts +66 -0
- package/src/hooks/useCustomerSupportHandoff.ts +39 -0
- package/src/hooks/useDebounce.ts +17 -0
- package/src/hooks/useDynamicVariants.ts +210 -0
- package/src/hooks/useElementObserver.ts +245 -0
- package/src/hooks/useFileUpload.ts +61 -0
- package/src/hooks/useGrabAndScroll.ts +133 -0
- package/src/hooks/useHideElements.ts +82 -0
- package/src/hooks/useHorizontalScrollAnimation.ts +115 -0
- package/src/hooks/useImageResolver.ts +51 -0
- package/src/hooks/useIntersection.ts +28 -0
- package/src/hooks/useIsSmallScreen.ts +23 -0
- package/src/hooks/useMessageFilter.ts +49 -0
- package/src/hooks/useMessageScrollObserver.ts +47 -0
- package/src/hooks/useReducedMotionWithOverride.ts +15 -0
- package/src/hooks/useSearch.tsx +433 -0
- package/src/hooks/useSnapCalculator.ts +38 -0
- package/src/hooks/useSnapControl.ts +155 -0
- package/src/hooks/useSystemSettingsContext.ts +12 -0
- package/src/hooks/useTrackComponentVisibleEvent.ts +52 -0
- package/src/hooks/useUpdateAnalyticsProps.ts +56 -0
- package/src/hooks/utils.ts +153 -0
- package/src/index.ts +31 -0
- package/src/initialize.ts +163 -0
- package/src/interceptors/types.ts +6 -0
- package/src/interceptors/useFormEscalation.ts +40 -0
- package/src/interceptors/useMessageInterceptor.ts +32 -0
- package/src/main.ts +85 -0
- package/src/main.tsx +123 -0
- package/src/merchants/bandolier/bandolier.ts +1389 -0
- package/src/merchants/carpe/carpe.ts +656 -0
- package/src/merchants/coterie/coterie.ts +280 -0
- package/src/merchants/default.ts +193 -0
- package/src/merchants/dreamlandBaby/dreamlandBaby.ts +375 -0
- package/src/merchants/fiveCbd/fiveCbd.ts +697 -0
- package/src/merchants/forLoveAndLemons/forLoveAndLemons.ts +721 -0
- package/src/merchants/greenpan/greenpan.ts +440 -0
- package/src/merchants/grooveLife/grooveLife.ts +386 -0
- package/src/merchants/homegrownCannabis/homegrownCannabis.ts +468 -0
- package/src/merchants/init-merchant.sh +53 -0
- package/src/merchants/jackArcher/jackArcher.ts +974 -0
- package/src/merchants/jordanCraig/jordanCraig.ts +1927 -0
- package/src/merchants/kindredBravely/kindredBravely.ts +529 -0
- package/src/merchants/kutFromTheKloth/kutFromTheKloth.ts +418 -0
- package/src/merchants/larryAndSerges/larryAndSerges.ts +314 -0
- package/src/merchants/leapsAndRebounds/leapsAndRebounds.ts +424 -0
- package/src/merchants/longevityrx/longevityrx.ts +368 -0
- package/src/merchants/lookOptic/lookOptic.ts +323 -0
- package/src/merchants/mantraBrand/mantraBrand.ts +838 -0
- package/src/merchants/medterra/medterra.ts +670 -0
- package/src/merchants/modells/modells.ts +546 -0
- package/src/merchants/pressedFloral/pressedFloral.ts +734 -0
- package/src/merchants/skinPerfection/skinPerfection.ts +379 -0
- package/src/merchants/snapSupplements/snapSupplements.ts +325 -0
- package/src/merchants/spanx/spanx.ts +810 -0
- package/src/merchants/spanx/spanxStaging.ts +942 -0
- package/src/merchants/supergoop/supergoop.ts +376 -0
- package/src/merchants/uniqueVintage/uniqueVintage.ts +1314 -0
- package/src/merchants/uniqueVintage/views/useUniqueVintageChatSearch.ts +147 -0
- package/src/merchants/venaCbd/venaCbd.ts +410 -0
- package/src/merchants/westonJonBoucher/westonJonBoucher.ts +473 -0
- package/src/merchants/wineEnthusiast/wineEnthusiast.ts +990 -0
- package/src/merchants/wolfMattress/wolfMattress.ts +411 -0
- package/src/merchants/wolfTactical/wolfTactical.ts +389 -0
- package/src/types/custservice-types.ts +28 -0
- package/src/types/search-filter-types.ts +111 -0
- package/src/types/suggestionBarV2-types.ts +4 -0
- package/src/types/test-types.ts +3 -0
- package/src/types.ts +66 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
|
|
2
|
+
class StringUtils {
|
|
3
|
+
static isNullOrEmpty(value: string | undefined): boolean {
|
|
4
|
+
const valueTrimmed = value?.trim();
|
|
5
|
+
return value === undefined || valueTrimmed === '';
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
static trimToNull(value: string | undefined): string | undefined {
|
|
9
|
+
const valueTrimmed = value?.trim();
|
|
10
|
+
return StringUtils.isNullOrEmpty(valueTrimmed) ? undefined : valueTrimmed;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static capitalize(type: string | undefined) {
|
|
14
|
+
if (type === undefined) {
|
|
15
|
+
return '';
|
|
16
|
+
}
|
|
17
|
+
return type.charAt(0).toUpperCase() + type.substring(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Finds the first pattern in an array that matches a given URL.
|
|
22
|
+
* Patterns can include a single wildcard '*' which matches any sequence of characters.
|
|
23
|
+
*
|
|
24
|
+
* @param patterns
|
|
25
|
+
* @param urlToTest
|
|
26
|
+
* @returns
|
|
27
|
+
*/
|
|
28
|
+
static findMatchingPattern(patterns: string[], urlToTest: Location): string | undefined {
|
|
29
|
+
if (!urlToTest) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
for (const pattern of patterns) {
|
|
34
|
+
// Test only if a pathname is present.
|
|
35
|
+
if (urlToTest.pathname !== '/') {
|
|
36
|
+
// Escape special regex characters in the pattern
|
|
37
|
+
// This ensures that characters like '.', '+', '?', '(', etc., in the pattern are treated literally.
|
|
38
|
+
const escapedPattern = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
|
|
39
|
+
|
|
40
|
+
// Replace the wildcard '*' with its regex equivalent '.*' (matches any character zero or more times)
|
|
41
|
+
const regexPattern = escapedPattern.replace(/\*/g, '.*');
|
|
42
|
+
|
|
43
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
44
|
+
if (regex.test(urlToTest.pathname)) {
|
|
45
|
+
return pattern;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
} else if (pattern.startsWith(urlToTest.hostname)) {
|
|
49
|
+
return pattern;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { StringUtils };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { SupportedEventRequest as ApiSupportedEventRequest } from '@spiffy-ai/commerce-api-client';
|
|
2
|
+
import { SupportedEventRequest as CoreSupportedEventRequest } from '../models/api/supportedEventRequest';
|
|
3
|
+
import { coreUserEventToApiUserEvent } from './coreUserEventToApiUserEvent';
|
|
4
|
+
import { coreContextToApiContext } from './coreContextToApiContext';
|
|
5
|
+
|
|
6
|
+
export const coreSupportedEventRequestToApiRequest = (
|
|
7
|
+
coreSupportedEventRequest: CoreSupportedEventRequest,
|
|
8
|
+
): ApiSupportedEventRequest => ({
|
|
9
|
+
id: coreSupportedEventRequest.id,
|
|
10
|
+
user_event: coreUserEventToApiUserEvent(coreSupportedEventRequest.userEvent),
|
|
11
|
+
context: coreContextToApiContext(coreSupportedEventRequest.context),
|
|
12
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { MessageRole, ProductSearchMessageMetadata } from '../models/message';
|
|
2
|
+
|
|
3
|
+
export const parseHref = (
|
|
4
|
+
href: string,
|
|
5
|
+
): { url: URL | undefined; urlSearchParams: URLSearchParams | undefined } => {
|
|
6
|
+
try {
|
|
7
|
+
const url = new URL(href);
|
|
8
|
+
const urlSearchParams = new URLSearchParams(url.search);
|
|
9
|
+
return { url, urlSearchParams };
|
|
10
|
+
} catch (e) {
|
|
11
|
+
return { url: undefined, urlSearchParams: undefined };
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const createUrlWithQueryParams = (
|
|
16
|
+
url: string,
|
|
17
|
+
queryParams: Record<string, string>,
|
|
18
|
+
): string => {
|
|
19
|
+
const urlObj = new URL(url, window.location.href);
|
|
20
|
+
Object.entries(queryParams).forEach(([value, key]) => urlObj.searchParams.append(value, key));
|
|
21
|
+
|
|
22
|
+
return urlObj.href;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const getQueryParam = (key: string): string | null => {
|
|
26
|
+
const urlObj = new URL(window.location.href);
|
|
27
|
+
return urlObj.searchParams.get(key);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
type SearchMessage = {
|
|
31
|
+
id: string;
|
|
32
|
+
role: MessageRole;
|
|
33
|
+
createdAt: string;
|
|
34
|
+
} & ProductSearchMessageMetadata;
|
|
35
|
+
|
|
36
|
+
export const buildSearchHash = (message: SearchMessage): string =>
|
|
37
|
+
`#evs=true&s=${message.id}&q=${message.metadata.generatedQuery}`;
|
|
38
|
+
|
|
39
|
+
export const buildSearchStartHash = (query: string): string => `#evs=true&q=${query}`;
|
|
40
|
+
|
|
41
|
+
// Basic parser for the search hash
|
|
42
|
+
export const parseSearchHash = (hash: string): { id: string | null; query: string | null } => {
|
|
43
|
+
if (!hash.startsWith('#evs=true')) {
|
|
44
|
+
return { id: null, query: null };
|
|
45
|
+
}
|
|
46
|
+
const params = Object.fromEntries(hash.split('&').map((param) => param.split('=')));
|
|
47
|
+
return {
|
|
48
|
+
id: params.s ? decodeURIComponent(params.s) : null,
|
|
49
|
+
query: params.q ? decodeURIComponent(params.q) : null,
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
window.history.pushState(null, '');
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// This email validates that there are one or more characters before the `@` symbol,
|
|
2
|
+
// one or more characters between the `@` symbol and the `.` symbol,
|
|
3
|
+
// and one or more characters after the `.` symbol
|
|
4
|
+
// It does NOT validate all possible email formats, but it is a decent place to start.
|
|
5
|
+
export const validateEmail = (value: string): boolean => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { ContextEnvEnum, ContextSourceEnum } from '@spiffy-ai/commerce-api-client';
|
|
2
|
+
import { atom } from 'jotai';
|
|
3
|
+
import { atomWithStorage } from 'jotai/utils';
|
|
4
|
+
import { VariantInfo } from 'src/application/models';
|
|
5
|
+
import { UserIdentityService } from 'src/application/service/userIdentityService';
|
|
6
|
+
import { variantInfoAtom } from 'src/atoms/app/variant';
|
|
7
|
+
import { orgIdAtom, orgShortNameAtom, sourceAtom } from 'src/atoms/org/org';
|
|
8
|
+
import { v4 as uuid } from 'uuid';
|
|
9
|
+
|
|
10
|
+
export interface AppDetails {
|
|
11
|
+
orgId: string;
|
|
12
|
+
orgShortName: string;
|
|
13
|
+
chatId: string;
|
|
14
|
+
userId: string;
|
|
15
|
+
source: ContextSourceEnum;
|
|
16
|
+
env: ContextEnvEnum;
|
|
17
|
+
variantInfo: VariantInfo;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { variantInfoAtom } from './variant';
|
|
21
|
+
|
|
22
|
+
const internalUserIdAtom = atom<string | undefined>(undefined);
|
|
23
|
+
|
|
24
|
+
export const userIdAtom = atom(
|
|
25
|
+
(get) => {
|
|
26
|
+
const maybeUserId = get(internalUserIdAtom);
|
|
27
|
+
|
|
28
|
+
if (maybeUserId) {
|
|
29
|
+
return maybeUserId;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return UserIdentityService.getUserIdOrDefault();
|
|
33
|
+
},
|
|
34
|
+
(_, set, value: string | undefined) => {
|
|
35
|
+
set(internalUserIdAtom, value);
|
|
36
|
+
},
|
|
37
|
+
);
|
|
38
|
+
export const appSourceAtom = atom<ContextSourceEnum>(
|
|
39
|
+
(get): ContextSourceEnum => get(sourceAtom) ?? ContextSourceEnum.App,
|
|
40
|
+
);
|
|
41
|
+
export const envAtom = atom<ContextEnvEnum>(ContextEnvEnum.Dev);
|
|
42
|
+
export const chatIdAtom = atomWithStorage<string>('v1-spiffy-chat-session-id', uuid(), undefined, {
|
|
43
|
+
getOnInit: true,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
export const appDetailsAtom = atom(
|
|
47
|
+
(get): AppDetails => ({
|
|
48
|
+
orgId: get(orgIdAtom),
|
|
49
|
+
// TODO: orgShortName should be available when this atom is created
|
|
50
|
+
orgShortName: get(orgShortNameAtom) ?? 'spiffy-ai',
|
|
51
|
+
chatId: get(chatIdAtom),
|
|
52
|
+
userId: get(userIdAtom),
|
|
53
|
+
source: get(appSourceAtom),
|
|
54
|
+
env: get(envAtom),
|
|
55
|
+
variantInfo: get(variantInfoAtom),
|
|
56
|
+
}),
|
|
57
|
+
);
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { atomWithStorage } from 'jotai/utils';
|
|
2
|
+
import { atom } from 'jotai';
|
|
3
|
+
import {
|
|
4
|
+
SupportedEventProductCategory,
|
|
5
|
+
SupportedEventResponse,
|
|
6
|
+
PageVisitCategory,
|
|
7
|
+
} from '@spiffy-ai/commerce-api-client';
|
|
8
|
+
import {
|
|
9
|
+
PageVisitVariantInfo,
|
|
10
|
+
PDPVariantInfo,
|
|
11
|
+
PLPVariantInfo,
|
|
12
|
+
VariantInfo,
|
|
13
|
+
FeatureGates,
|
|
14
|
+
OrgShortName,
|
|
15
|
+
} from 'src/application/models';
|
|
16
|
+
import { sessionStorageUtil } from 'src/atoms/atomStore';
|
|
17
|
+
import { featureFlagServiceAtom, orgShortNameAtom } from 'src/atoms/org/org';
|
|
18
|
+
|
|
19
|
+
export interface SupportedEvent
|
|
20
|
+
extends Pick<
|
|
21
|
+
SupportedEventResponse,
|
|
22
|
+
'supported' | 'ready' | 'category' | 'collections' | 'top_category'
|
|
23
|
+
> {
|
|
24
|
+
numberOfReviews: number | undefined;
|
|
25
|
+
merchant_tags?: string[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface PDPAttributes {
|
|
29
|
+
product_id?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface PLPAttributes {
|
|
33
|
+
attributes?: {
|
|
34
|
+
id?: string;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface UrlResolvingPDPConfig {
|
|
39
|
+
pdp_attributes: PDPAttributes;
|
|
40
|
+
number_of_reviews?: number;
|
|
41
|
+
collections?: string[];
|
|
42
|
+
merchant_tags?: string[];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface UrlResolvingPLPConfig {
|
|
46
|
+
plp_attributes: PLPAttributes;
|
|
47
|
+
top_category?: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface UrlResolvingGenericConfig {
|
|
51
|
+
details?: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export type PageVariantCheckConfig = {
|
|
55
|
+
check_type: string;
|
|
56
|
+
feature_gate?: string;
|
|
57
|
+
extractor?: {
|
|
58
|
+
type: string;
|
|
59
|
+
map?: Record<string, string[]>;
|
|
60
|
+
value?: string;
|
|
61
|
+
};
|
|
62
|
+
product_id_extractor?: string;
|
|
63
|
+
product_ids?: string[];
|
|
64
|
+
plp_id_extractor?: string;
|
|
65
|
+
plp_ids?: string[];
|
|
66
|
+
collections?: string[];
|
|
67
|
+
query_param?: string;
|
|
68
|
+
category?: string;
|
|
69
|
+
top_category?: string[];
|
|
70
|
+
review_minimum?: number;
|
|
71
|
+
merchant_tags?: string[];
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export type BackendWidgetMountingConfig = {
|
|
75
|
+
mounting_config_id: string;
|
|
76
|
+
widget_config_id?: string;
|
|
77
|
+
mounting_point_widgets?: Array<{
|
|
78
|
+
checks: PageVariantCheckConfig[];
|
|
79
|
+
widget_config_id: string;
|
|
80
|
+
}>;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export type BackendPageVariantConfig = {
|
|
84
|
+
variant_id: string;
|
|
85
|
+
variant_type: string;
|
|
86
|
+
variant_checks: PageVariantCheckConfig[];
|
|
87
|
+
widget_mounting: BackendWidgetMountingConfig[];
|
|
88
|
+
plp_id_extractor?: string;
|
|
89
|
+
product_id_extractor?: string;
|
|
90
|
+
parent_product_id_extractor?: string;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export interface UrlResolverResponse {
|
|
94
|
+
variant_type: string;
|
|
95
|
+
specific_details: UrlResolvingPDPConfig | UrlResolvingPLPConfig | UrlResolvingGenericConfig;
|
|
96
|
+
ready: boolean;
|
|
97
|
+
user_event?: {
|
|
98
|
+
event_id?: string;
|
|
99
|
+
attributes?: PDPAttributes | PLPAttributes;
|
|
100
|
+
category?: string;
|
|
101
|
+
created_at?: string;
|
|
102
|
+
};
|
|
103
|
+
page_variant?: BackendPageVariantConfig;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Use a map for per-URL cache
|
|
107
|
+
export type UrlResolverCache = Record<string, UrlResolverResponse | undefined>;
|
|
108
|
+
|
|
109
|
+
const internalStorageUrlResolverAtom = atomWithStorage<string | undefined>(
|
|
110
|
+
'spiffy-url-resolver',
|
|
111
|
+
undefined,
|
|
112
|
+
sessionStorageUtil,
|
|
113
|
+
{
|
|
114
|
+
getOnInit: true,
|
|
115
|
+
},
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
export const urlResolverAtom = atom(
|
|
119
|
+
(get): UrlResolverCache => {
|
|
120
|
+
const maybeUrlResolver = get(internalStorageUrlResolverAtom);
|
|
121
|
+
if (maybeUrlResolver == null) {
|
|
122
|
+
return {};
|
|
123
|
+
}
|
|
124
|
+
return JSON.parse(maybeUrlResolver);
|
|
125
|
+
},
|
|
126
|
+
(get, set, value: { url: string; response: UrlResolverResponse | undefined }) => {
|
|
127
|
+
// Get current cache from storage
|
|
128
|
+
const currentCache = get(urlResolverAtom);
|
|
129
|
+
const newCache = { ...currentCache, [value.url]: value.response };
|
|
130
|
+
|
|
131
|
+
set(internalStorageUrlResolverAtom, JSON.stringify(newCache));
|
|
132
|
+
},
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
const internalStorageSupportedEventAtom = atomWithStorage<string | undefined>(
|
|
136
|
+
'spiffy-supported-event',
|
|
137
|
+
undefined,
|
|
138
|
+
sessionStorageUtil,
|
|
139
|
+
{
|
|
140
|
+
getOnInit: true,
|
|
141
|
+
},
|
|
142
|
+
);
|
|
143
|
+
const internalSupportedEventAtom = atom<SupportedEvent | undefined>(undefined);
|
|
144
|
+
|
|
145
|
+
export const supportedEventAtom = atom(
|
|
146
|
+
(get): SupportedEvent | undefined => {
|
|
147
|
+
const maybeSupportedEvent = get(internalStorageSupportedEventAtom);
|
|
148
|
+
if (maybeSupportedEvent == null) {
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// TODO this is an unvalidated parse. It may be better to implement a custom storage util
|
|
153
|
+
// and perform the object validation on "get" there.
|
|
154
|
+
return JSON.parse(maybeSupportedEvent);
|
|
155
|
+
},
|
|
156
|
+
(get, set, value: SupportedEvent | undefined) => {
|
|
157
|
+
if (value == null) {
|
|
158
|
+
set(internalStorageSupportedEventAtom, undefined);
|
|
159
|
+
set(internalSupportedEventAtom, undefined);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const featureFlagService = get(featureFlagServiceAtom);
|
|
164
|
+
const maybeSupportedEvent = get(internalSupportedEventAtom);
|
|
165
|
+
const variantCategory = maybeSupportedEvent?.category;
|
|
166
|
+
const shortName = get(orgShortNameAtom);
|
|
167
|
+
|
|
168
|
+
// TODO: clean up this logic & the feature gate when we've fully rolled out
|
|
169
|
+
if (
|
|
170
|
+
!featureFlagService.isFeatureGateEnabled(FeatureGates.IsNonShapewearEnabled) &&
|
|
171
|
+
variantCategory &&
|
|
172
|
+
variantCategory !== SupportedEventProductCategory.Shapewear &&
|
|
173
|
+
(shortName === OrgShortName.Spanx || shortName === OrgShortName.SpanxStaging)
|
|
174
|
+
) {
|
|
175
|
+
const modifiedSupportedEvent = {
|
|
176
|
+
supported: false,
|
|
177
|
+
ready: value.ready,
|
|
178
|
+
category: value.category,
|
|
179
|
+
numberOfReviews: value.numberOfReviews,
|
|
180
|
+
collections: value.collections,
|
|
181
|
+
top_category: value.top_category,
|
|
182
|
+
merchant_tags: value.merchant_tags,
|
|
183
|
+
};
|
|
184
|
+
set(internalSupportedEventAtom, modifiedSupportedEvent);
|
|
185
|
+
set(internalStorageSupportedEventAtom, JSON.stringify(modifiedSupportedEvent));
|
|
186
|
+
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
set(internalSupportedEventAtom, value);
|
|
191
|
+
set(internalStorageSupportedEventAtom, JSON.stringify(value));
|
|
192
|
+
},
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
const internalVariantIdAtom = atom<string>();
|
|
196
|
+
const internalProductIdAtom = atom<string>();
|
|
197
|
+
const internalParentProductIdAtom = atom<string>();
|
|
198
|
+
const internalProductUrlAtom = atom<string>();
|
|
199
|
+
const internalPlpIdAtom = atom<string>();
|
|
200
|
+
const internalUrlAtom = atom<string>();
|
|
201
|
+
const internalPageVisitCategoryAtom = atom<PageVisitCategory>();
|
|
202
|
+
const internalVariantAtom = atom<'pdp' | 'plp' | 'search' | 'page_visit'>('pdp');
|
|
203
|
+
|
|
204
|
+
export const variantIdAtom = atom((get) => get(internalVariantIdAtom));
|
|
205
|
+
export const productIdAtom = atom((get) => get(internalProductIdAtom));
|
|
206
|
+
export const parentProductIdAtom = atom((get) => get(internalParentProductIdAtom));
|
|
207
|
+
export const productUrlAtom = atom((get) => get(internalProductUrlAtom));
|
|
208
|
+
export const plpIdAtom = atom((get) => get(internalPlpIdAtom));
|
|
209
|
+
export const urlAtom = atom((get) => get(internalUrlAtom));
|
|
210
|
+
export const pageVisitCategoryAtom = atom((get) => get(internalPageVisitCategoryAtom));
|
|
211
|
+
export const variantAtom = atom((get) => get(internalVariantAtom));
|
|
212
|
+
export const hasParsedVariantInfoAtom = atom(false);
|
|
213
|
+
|
|
214
|
+
export const variantInfoAtom = atom(
|
|
215
|
+
(get): VariantInfo => {
|
|
216
|
+
const variant = get(variantAtom);
|
|
217
|
+
if (variant === 'pdp') {
|
|
218
|
+
return {
|
|
219
|
+
variantId: get(variantIdAtom),
|
|
220
|
+
variant,
|
|
221
|
+
productId: get(productIdAtom),
|
|
222
|
+
parentProductId: get(parentProductIdAtom),
|
|
223
|
+
url: get(urlAtom),
|
|
224
|
+
} as PDPVariantInfo;
|
|
225
|
+
}
|
|
226
|
+
if (variant === 'plp') {
|
|
227
|
+
return {
|
|
228
|
+
variantId: get(variantIdAtom),
|
|
229
|
+
variant,
|
|
230
|
+
plpId: get(plpIdAtom),
|
|
231
|
+
url: get(urlAtom),
|
|
232
|
+
} as PLPVariantInfo;
|
|
233
|
+
}
|
|
234
|
+
if (variant === 'page_visit') {
|
|
235
|
+
return {
|
|
236
|
+
variantId: get(variantIdAtom),
|
|
237
|
+
variant,
|
|
238
|
+
url: get(urlAtom),
|
|
239
|
+
pageVisitCategory: get(pageVisitCategoryAtom),
|
|
240
|
+
} as PageVisitVariantInfo;
|
|
241
|
+
}
|
|
242
|
+
throw new Error('Invalid variantInfo details');
|
|
243
|
+
},
|
|
244
|
+
(_, set, newVariant: VariantInfo) => {
|
|
245
|
+
set(internalVariantAtom, newVariant.variant);
|
|
246
|
+
set(internalVariantIdAtom, newVariant.variantId);
|
|
247
|
+
if (newVariant.variant === 'pdp') {
|
|
248
|
+
set(internalProductIdAtom, newVariant.productId);
|
|
249
|
+
set(internalParentProductIdAtom, newVariant.parentProductId);
|
|
250
|
+
set(internalUrlAtom, newVariant.url);
|
|
251
|
+
}
|
|
252
|
+
if (newVariant.variant === 'plp') {
|
|
253
|
+
set(internalPlpIdAtom, newVariant.plpId);
|
|
254
|
+
set(internalUrlAtom, newVariant.url);
|
|
255
|
+
}
|
|
256
|
+
if (newVariant.variant === 'page_visit') {
|
|
257
|
+
set(internalUrlAtom, newVariant.url);
|
|
258
|
+
set(internalPageVisitCategoryAtom, newVariant.pageVisitCategory);
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { getDefaultStore } from 'jotai';
|
|
2
|
+
import { createJSONStorage } from 'jotai/utils';
|
|
3
|
+
|
|
4
|
+
export type AtomStore = ReturnType<typeof getDefaultStore>;
|
|
5
|
+
let atomStore: AtomStore | null = null;
|
|
6
|
+
|
|
7
|
+
export const getAtomStore = (): AtomStore => {
|
|
8
|
+
if (!atomStore) {
|
|
9
|
+
atomStore = getDefaultStore();
|
|
10
|
+
}
|
|
11
|
+
return atomStore;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @internal
|
|
16
|
+
*
|
|
17
|
+
* Sets the global atom store to be the provided store.
|
|
18
|
+
*
|
|
19
|
+
* @param store - The store to set the global atom store to.
|
|
20
|
+
*/
|
|
21
|
+
export const setAtomStoreForTesting = (store: AtomStore) => {
|
|
22
|
+
atomStore = store;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @internal
|
|
27
|
+
*
|
|
28
|
+
* Resets the global atom store to null
|
|
29
|
+
*/
|
|
30
|
+
export const resetAtomStore = () => {
|
|
31
|
+
atomStore = null;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const sessionStorageUtil = createJSONStorage<string | undefined>(() => sessionStorage);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { UserEventCategory } from '@spiffy-ai/commerce-api-client/dist/models/UserEventCategory';
|
|
2
|
+
import { atom } from 'jotai';
|
|
3
|
+
import { AmplitudeAdapter, SpiffyMetricsEventName } from 'src/adapters/amplitude';
|
|
4
|
+
import { FormSubmittedAttributes, Message, Suggestion, UserEvent } from 'src/application/models';
|
|
5
|
+
import { ChatElementDisplayLocation } from 'src/application/models/chatElementDisplayLocation';
|
|
6
|
+
import { SpiffyEventName } from 'src/application/models/events';
|
|
7
|
+
|
|
8
|
+
export const userHasRepliedAtom = atom<boolean>(false);
|
|
9
|
+
export const replyEventCategoryAtom = atom<UserEventCategory>(UserEventCategory.AppLoaded);
|
|
10
|
+
export const userQueryAtom = atom<string>();
|
|
11
|
+
export const suggestionAtom = atom<Suggestion | undefined>(undefined);
|
|
12
|
+
export const askQuestionBtnClickedAtom = atom<boolean>(false);
|
|
13
|
+
export const messagesAtom = atom<Message[][]>([]);
|
|
14
|
+
export const userEventsAtom = atom<UserEvent[]>([]);
|
|
15
|
+
export const suggestionsAtom = atom<Suggestion[]>([]);
|
|
16
|
+
export const suggestionsLoadingAtom = atom<boolean>(false);
|
|
17
|
+
export const responseStreamingAtom = atom<boolean>(false);
|
|
18
|
+
export const chatIsOpenAtom = atom<boolean>(false);
|
|
19
|
+
export const requestFailureAtom = atom<boolean>(false);
|
|
20
|
+
export const formSubmitAtom = atom<FormSubmittedAttributes>();
|
|
21
|
+
export const chatOnToggleAtom = atom(
|
|
22
|
+
null,
|
|
23
|
+
(get, set, triggerLocation?: ChatElementDisplayLocation) => {
|
|
24
|
+
const isOpen = get(chatIsOpenAtom);
|
|
25
|
+
set(chatIsOpenAtom, !isOpen);
|
|
26
|
+
|
|
27
|
+
if (!isOpen) {
|
|
28
|
+
window.dispatchEvent(new CustomEvent(SpiffyEventName.WidgetOpen));
|
|
29
|
+
AmplitudeAdapter.trackEvent({
|
|
30
|
+
eventName: SpiffyMetricsEventName.ChatComponentExpanded,
|
|
31
|
+
eventProps: {
|
|
32
|
+
message_metadata: {
|
|
33
|
+
trigger_location: triggerLocation,
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
} else {
|
|
38
|
+
window.dispatchEvent(new CustomEvent(SpiffyEventName.WidgetClose));
|
|
39
|
+
AmplitudeAdapter.trackEvent({
|
|
40
|
+
eventName: SpiffyMetricsEventName.ChatComponentCollapsed,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { UserEventCategory } from '@spiffy-ai/commerce-api-client';
|
|
2
|
+
import { atom } from 'jotai';
|
|
3
|
+
import { FormSubmittedAttributes, UserEvent } from 'src/application/models';
|
|
4
|
+
import { v4 as uuid } from 'uuid';
|
|
5
|
+
import { formSubmitAtom, replyEventCategoryAtom } from 'src/atoms/chat';
|
|
6
|
+
import { queueUserEventAtom } from 'src/atoms/chat/messageQueue';
|
|
7
|
+
|
|
8
|
+
export const handleFormSubmittedAtom = atom(null, (_, set, form: FormSubmittedAttributes) => {
|
|
9
|
+
set(replyEventCategoryAtom, UserEventCategory.FormSubmitted);
|
|
10
|
+
set(formSubmitAtom, form);
|
|
11
|
+
|
|
12
|
+
const formUserEvent = {
|
|
13
|
+
eventId: uuid(),
|
|
14
|
+
category: UserEventCategory.FormSubmitted,
|
|
15
|
+
createdAt: new Date().toISOString(),
|
|
16
|
+
attributes: form,
|
|
17
|
+
} satisfies UserEvent;
|
|
18
|
+
set(queueUserEventAtom, formUserEvent);
|
|
19
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { atom } from 'jotai';
|
|
2
|
+
import {
|
|
3
|
+
responseStreamingAtom,
|
|
4
|
+
suggestionsLoadingAtom,
|
|
5
|
+
messagesAtom,
|
|
6
|
+
userQueryAtom,
|
|
7
|
+
replyEventCategoryAtom,
|
|
8
|
+
userHasRepliedAtom,
|
|
9
|
+
askQuestionBtnClickedAtom,
|
|
10
|
+
suggestionsAtom,
|
|
11
|
+
chatIsOpenAtom,
|
|
12
|
+
chatOnToggleAtom,
|
|
13
|
+
userEventsAtom,
|
|
14
|
+
suggestionAtom,
|
|
15
|
+
} from './chatState';
|
|
16
|
+
|
|
17
|
+
export * from './chatState';
|
|
18
|
+
export * from './replies';
|
|
19
|
+
export * from './performanceMetrics';
|
|
20
|
+
export * from './form';
|
|
21
|
+
export * from './suggestions';
|
|
22
|
+
export * from './lastMessage';
|
|
23
|
+
export * from './renderedWidgetRefs';
|
|
24
|
+
|
|
25
|
+
export const chatAtom = atom((get) => ({
|
|
26
|
+
userHasReplied: get(userHasRepliedAtom),
|
|
27
|
+
replyEventCategory: get(replyEventCategoryAtom),
|
|
28
|
+
userQuery: get(userQueryAtom),
|
|
29
|
+
suggestion: get(suggestionAtom),
|
|
30
|
+
askQuestionBtnClicked: get(askQuestionBtnClickedAtom),
|
|
31
|
+
messages: get(messagesAtom),
|
|
32
|
+
userEvents: get(userEventsAtom),
|
|
33
|
+
suggestions: get(suggestionsAtom),
|
|
34
|
+
suggestionsLoading: get(suggestionsLoadingAtom),
|
|
35
|
+
responseStreaming: get(responseStreamingAtom),
|
|
36
|
+
isOpen: get(chatIsOpenAtom),
|
|
37
|
+
onToggle: get(chatOnToggleAtom),
|
|
38
|
+
}));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { atom } from 'jotai';
|
|
2
|
+
import { messagesAtom, userHasRepliedAtom } from 'src/atoms/chat';
|
|
3
|
+
|
|
4
|
+
export const lastAssistantMessageAtom = atom((get) => {
|
|
5
|
+
const messages = get(messagesAtom);
|
|
6
|
+
const userHasReplied = get(userHasRepliedAtom);
|
|
7
|
+
if (messages.length > 0 && !userHasReplied) {
|
|
8
|
+
return messages[messages.length - 1];
|
|
9
|
+
}
|
|
10
|
+
return null;
|
|
11
|
+
});
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { atom } from 'jotai';
|
|
2
|
+
import { v4 as uuid } from 'uuid';
|
|
3
|
+
import { GenerationParams, NextMessageRequest, UserEvent } from 'src/application/models';
|
|
4
|
+
import { getAtomStore } from 'src/atoms/atomStore';
|
|
5
|
+
import { appDetailsAtom } from 'src/atoms/app';
|
|
6
|
+
import { featureFlagServiceAtom } from 'src/atoms/org/org';
|
|
7
|
+
|
|
8
|
+
const internalUserEventQueueAtom = atom<UserEvent[]>([]);
|
|
9
|
+
|
|
10
|
+
export const userEventQueueAtom = atom((get) => {
|
|
11
|
+
const queue = get(internalUserEventQueueAtom);
|
|
12
|
+
return queue === undefined ? [] : queue.filter((v) => v !== undefined);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* This atom is used to queue a new message for processing on `next_responses`
|
|
17
|
+
* It receives a single `userEvent` that is added to the processing queue.
|
|
18
|
+
* If the event has the same eventId as an existing message in the queue the NEW
|
|
19
|
+
* event is ignored
|
|
20
|
+
*/
|
|
21
|
+
export const queueUserEventAtom = atom(null, (get, set, userEvent: UserEvent) => {
|
|
22
|
+
if (userEvent === undefined) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
set(internalUserEventQueueAtom, [...get(internalUserEventQueueAtom), userEvent]);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* This atom exposes a function to reset the entire queue. All messages in the queue will be purged
|
|
30
|
+
*/
|
|
31
|
+
export const clearUserEventAtom = atom(null, (_, set) => {
|
|
32
|
+
set(internalUserEventQueueAtom, []);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* This atom is used to mark events as processed and remove them from the queue
|
|
37
|
+
* It accepts a list of eventId values and will remove all events with those eventIds from the queue.
|
|
38
|
+
*/
|
|
39
|
+
export const processUserEventAtom = atom(null, (get, set, eventIds: string[]) => {
|
|
40
|
+
const curr = get(internalUserEventQueueAtom);
|
|
41
|
+
const remaining = curr?.filter((event) => !eventIds.includes(event.eventId));
|
|
42
|
+
set(internalUserEventQueueAtom, remaining);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
export const userQueueEventCountAtom = atom((get) => get(userEventQueueAtom).length);
|
|
46
|
+
|
|
47
|
+
export const createResponsePayload = ({
|
|
48
|
+
userEvents,
|
|
49
|
+
generationParams,
|
|
50
|
+
}: {
|
|
51
|
+
userEvents: UserEvent[];
|
|
52
|
+
generationParams?: GenerationParams;
|
|
53
|
+
}): NextMessageRequest => {
|
|
54
|
+
const atomStore = getAtomStore();
|
|
55
|
+
const context = atomStore.get(appDetailsAtom);
|
|
56
|
+
const featureFlagService = atomStore.get(featureFlagServiceAtom);
|
|
57
|
+
const featureFlags = featureFlagService.getFeatureFlags();
|
|
58
|
+
return {
|
|
59
|
+
id: uuid(),
|
|
60
|
+
context,
|
|
61
|
+
userEvents,
|
|
62
|
+
featureFlags,
|
|
63
|
+
generationParams,
|
|
64
|
+
};
|
|
65
|
+
};
|