@salla.sa/twilight-theme-engine 1.0.144 → 1.0.146
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/dist/{AddToCartForm-LWT2QINY.js → AddToCartForm-ZZMT3ZRO.js} +3 -3
- package/dist/{AddToCartForm-LWT2QINY.js.map → AddToCartForm-ZZMT3ZRO.js.map} +1 -1
- package/dist/{BlogAuthorPage-52C2OHXW.js → BlogAuthorPage-LVRGWFOC.js} +27 -27
- package/dist/{BlogAuthorPage-52C2OHXW.js.map → BlogAuthorPage-LVRGWFOC.js.map} +1 -1
- package/dist/{BlogCategoryPage-LBLIAN6Q.js → BlogCategoryPage-CONL6QSN.js} +27 -27
- package/dist/{BlogCategoryPage-LBLIAN6Q.js.map → BlogCategoryPage-CONL6QSN.js.map} +1 -1
- package/dist/{BlogPage-U56CLHI4.js → BlogPage-6ZA474IU.js} +25 -25
- package/dist/{BlogPage-U56CLHI4.js.map → BlogPage-6ZA474IU.js.map} +1 -1
- package/dist/{BlogSinglePage-NQJDYUFB.js → BlogSinglePage-W7WYKP7W.js} +25 -25
- package/dist/{BlogSinglePage-NQJDYUFB.js.map → BlogSinglePage-W7WYKP7W.js.map} +1 -1
- package/dist/{BlogTagPage-XP3XGVCO.js → BlogTagPage-G5JX7FSN.js} +27 -27
- package/dist/{BlogTagPage-XP3XGVCO.js.map → BlogTagPage-G5JX7FSN.js.map} +1 -1
- package/dist/{BrandsPage-22AET7DW.js → BrandsPage-TB5NDSGL.js} +26 -26
- package/dist/{BrandsPage-22AET7DW.js.map → BrandsPage-TB5NDSGL.js.map} +1 -1
- package/dist/{Breadcrumb-YTYXSTKO.js → Breadcrumb-EVZDJG7H.js} +25 -25
- package/dist/{Breadcrumb-YTYXSTKO.js.map → Breadcrumb-EVZDJG7H.js.map} +1 -1
- package/dist/{CartItem-UTU4GLDN.js → CartItem-D2LJIFGL.js} +25 -25
- package/dist/{CartItem-UTU4GLDN.js.map → CartItem-D2LJIFGL.js.map} +1 -1
- package/dist/{CartSummary-4UGWZ3B3.js → CartSummary-V4HYUEPB.js} +25 -25
- package/dist/{CartSummary-4UGWZ3B3.js.map → CartSummary-V4HYUEPB.js.map} +1 -1
- package/dist/{Copyright-B2GYPZBZ.js → Copyright-JLIFLENS.js} +3 -3
- package/dist/{Copyright-B2GYPZBZ.js.map → Copyright-JLIFLENS.js.map} +1 -1
- package/dist/{CustomerLayout-I4XFBCOH.js → CustomerLayout-JSIYPWY4.js} +25 -25
- package/dist/{CustomerLayout-I4XFBCOH.js.map → CustomerLayout-JSIYPWY4.js.map} +1 -1
- package/dist/{Footer-OWOF2AGC.js → Footer-BNIVXKRM.js} +4 -4
- package/dist/{Footer-OWOF2AGC.js.map → Footer-BNIVXKRM.js.map} +1 -1
- package/dist/{Header-KDJL4YRP.js → Header-DI3OK5TC.js} +11 -11
- package/dist/{Header-KDJL4YRP.js.map → Header-DI3OK5TC.js.map} +1 -1
- package/dist/{LatestProducts-YBFHXG5V.js → LatestProducts-PEIN355E.js} +27 -27
- package/dist/{LatestProducts-YBFHXG5V.js.map → LatestProducts-PEIN355E.js.map} +1 -1
- package/dist/{LoyaltyPage-GFWTFQA7.js → LoyaltyPage-GV6WMYVE.js} +25 -25
- package/dist/{LoyaltyPage-GFWTFQA7.js.map → LoyaltyPage-GV6WMYVE.js.map} +1 -1
- package/dist/{LoyaltyPointsPage-WJDZL6G4.js → LoyaltyPointsPage-QNOVSCKB.js} +8 -8
- package/dist/{LoyaltyPointsPage-WJDZL6G4.js.map → LoyaltyPointsPage-QNOVSCKB.js.map} +1 -1
- package/dist/{MainMenu-AWSLHAEE.js → MainMenu-IN5HUX3U.js} +7 -7
- package/dist/{MainMenu-AWSLHAEE.js.map → MainMenu-IN5HUX3U.js.map} +1 -1
- package/dist/{MasterLayout-ZMHHLGYL.js → MasterLayout-GHAXKYOR.js} +25 -25
- package/dist/{MasterLayout-ZMHHLGYL.js.map → MasterLayout-GHAXKYOR.js.map} +1 -1
- package/dist/{MobileMenu-56MF2EAS.js → MobileMenu-XU45EZMG.js} +26 -26
- package/dist/{MobileMenu-56MF2EAS.js.map → MobileMenu-XU45EZMG.js.map} +1 -1
- package/dist/{NotificationsPage-7QC66446.js → NotificationsPage-AMY7TARF.js} +25 -25
- package/dist/{NotificationsPage-7QC66446.js.map → NotificationsPage-AMY7TARF.js.map} +1 -1
- package/dist/{OrderSinglePage-WXJHUJ6C.js → OrderSinglePage-L2E6YH3Z.js} +26 -26
- package/dist/{OrderSinglePage-WXJHUJ6C.js.map → OrderSinglePage-L2E6YH3Z.js.map} +1 -1
- package/dist/{OrdersPage-ZNM4YGXR.js → OrdersPage-76ORWMJY.js} +25 -25
- package/dist/{OrdersPage-ZNM4YGXR.js.map → OrdersPage-76ORWMJY.js.map} +1 -1
- package/dist/{PageSingle-NQZM6O5A.js → PageSingle-D7I6EHBF.js} +6 -6
- package/dist/{PageSingle-NQZM6O5A.js.map → PageSingle-D7I6EHBF.js.map} +1 -1
- package/dist/{ProductDetails-N4KYBKBG.js → ProductDetails-BZVRXSCD.js} +7 -7
- package/dist/{ProductDetails-N4KYBKBG.js.map → ProductDetails-BZVRXSCD.js.map} +1 -1
- package/dist/{ProfilePage-XOGVATHX.js → ProfilePage-65NYRBON.js} +25 -25
- package/dist/{ProfilePage-XOGVATHX.js.map → ProfilePage-65NYRBON.js.map} +1 -1
- package/dist/{ReviewsPage-WOLLCLAY.js → ReviewsPage-C7NSCMBE.js} +3 -3
- package/dist/{ReviewsPage-WOLLCLAY.js.map → ReviewsPage-C7NSCMBE.js.map} +1 -1
- package/dist/{SeoCartWidget-EVJOTXPO.js → SeoCartWidget-GK3KC2M3.js} +25 -25
- package/dist/{SeoCartWidget-EVJOTXPO.js.map → SeoCartWidget-GK3KC2M3.js.map} +1 -1
- package/dist/{SettingsPage-LYDZFUF3.js → SettingsPage-7VGJBA5K.js} +25 -25
- package/dist/{SettingsPage-LYDZFUF3.js.map → SettingsPage-7VGJBA5K.js.map} +1 -1
- package/dist/{StoreClosedNotification-62SFSGRH.js → StoreClosedNotification-44JN2FZV.js} +26 -26
- package/dist/{StoreClosedNotification-62SFSGRH.js.map → StoreClosedNotification-44JN2FZV.js.map} +1 -1
- package/dist/{TestimonialsPage-WPZBQQO2.js → TestimonialsPage-KGCGTUJQ.js} +6 -6
- package/dist/{TestimonialsPage-WPZBQQO2.js.map → TestimonialsPage-KGCGTUJQ.js.map} +1 -1
- package/dist/{ThankYouPage-44VMBXGI.js → ThankYouPage-XWB4X236.js} +25 -25
- package/dist/{ThankYouPage-44VMBXGI.js.map → ThankYouPage-XWB4X236.js.map} +1 -1
- package/dist/{WalletPage-YVSIECSM.js → WalletPage-J3CX6MLS.js} +26 -26
- package/dist/{WalletPage-YVSIECSM.js.map → WalletPage-J3CX6MLS.js.map} +1 -1
- package/dist/{WebMcpTools-VA2A62E3.js → WebMcpTools-3MV53OMT.js} +9 -9
- package/dist/{WebMcpTools-VA2A62E3.js.map → WebMcpTools-3MV53OMT.js.map} +1 -1
- package/dist/{WishlistPage-IGWDG4HC.js → WishlistPage-HHX3OVOF.js} +27 -27
- package/dist/{WishlistPage-IGWDG4HC.js.map → WishlistPage-HHX3OVOF.js.map} +1 -1
- package/dist/api/advertisement.js +4 -4
- package/dist/api/apps.js +4 -4
- package/dist/api/blog.js +6 -6
- package/dist/api/brands.js +6 -6
- package/dist/api/cart.js +6 -6
- package/dist/api/category.js +6 -6
- package/dist/api/client.js +3 -3
- package/dist/api/home.js +4 -4
- package/dist/api/loyalty.js +6 -6
- package/dist/api/menu.js +4 -4
- package/dist/api/notification.js +4 -4
- package/dist/api/order.js +6 -6
- package/dist/api/page.js +6 -6
- package/dist/api/product.js +6 -6
- package/dist/api/profile.js +3 -3
- package/dist/api/store.js +5 -5
- package/dist/api/translations.js +4 -4
- package/dist/api/user.js +4 -4
- package/dist/api/wallet.js +4 -4
- package/dist/api/wishlist.js +7 -7
- package/dist/{chunk-G3NCSKQ3.js → chunk-2DUN6DZK.js} +5 -5
- package/dist/{chunk-G3NCSKQ3.js.map → chunk-2DUN6DZK.js.map} +1 -1
- package/dist/{chunk-S4KV6QGP.js → chunk-3G4YCXOR.js} +27 -20
- package/dist/chunk-3G4YCXOR.js.map +1 -0
- package/dist/{chunk-IVZNTLAA.js → chunk-3O6BB7SI.js} +3 -3
- package/dist/{chunk-IVZNTLAA.js.map → chunk-3O6BB7SI.js.map} +1 -1
- package/dist/{chunk-5XWGYFZ2.js → chunk-3QOALQQJ.js} +4 -4
- package/dist/{chunk-5XWGYFZ2.js.map → chunk-3QOALQQJ.js.map} +1 -1
- package/dist/{chunk-7IQFONJR.js → chunk-5EN3XZ32.js} +3 -3
- package/dist/{chunk-7IQFONJR.js.map → chunk-5EN3XZ32.js.map} +1 -1
- package/dist/{chunk-N6ZE6HUX.js → chunk-5V4W3GBI.js} +5 -5
- package/dist/{chunk-N6ZE6HUX.js.map → chunk-5V4W3GBI.js.map} +1 -1
- package/dist/{chunk-3E3ABCPC.js → chunk-6TFM3UTF.js} +3 -3
- package/dist/{chunk-3E3ABCPC.js.map → chunk-6TFM3UTF.js.map} +1 -1
- package/dist/{chunk-WATFGHFK.js → chunk-7PPNAVBF.js} +4 -4
- package/dist/{chunk-WATFGHFK.js.map → chunk-7PPNAVBF.js.map} +1 -1
- package/dist/{chunk-GCXFTIHV.js → chunk-7ZTSYUCJ.js} +4 -4
- package/dist/{chunk-GCXFTIHV.js.map → chunk-7ZTSYUCJ.js.map} +1 -1
- package/dist/{chunk-BBQATCYN.js → chunk-A4Y5BVJN.js} +3 -3
- package/dist/{chunk-BBQATCYN.js.map → chunk-A4Y5BVJN.js.map} +1 -1
- package/dist/{chunk-IAM44RPN.js → chunk-AECYX56P.js} +4 -4
- package/dist/{chunk-IAM44RPN.js.map → chunk-AECYX56P.js.map} +1 -1
- package/dist/{chunk-AT6YLLT4.js → chunk-B36NISD2.js} +4 -4
- package/dist/{chunk-AT6YLLT4.js.map → chunk-B36NISD2.js.map} +1 -1
- package/dist/{chunk-BXMU3ARO.js → chunk-BEYWTFOR.js} +4 -4
- package/dist/{chunk-BXMU3ARO.js.map → chunk-BEYWTFOR.js.map} +1 -1
- package/dist/{chunk-AXTVBTO4.js → chunk-BKSVKSAW.js} +22 -22
- package/dist/{chunk-AXTVBTO4.js.map → chunk-BKSVKSAW.js.map} +1 -1
- package/dist/{chunk-KVBWIXXG.js → chunk-C5P2C2NR.js} +3 -3
- package/dist/{chunk-KVBWIXXG.js.map → chunk-C5P2C2NR.js.map} +1 -1
- package/dist/{chunk-PYUTATUY.js → chunk-C6PNF2OT.js} +3 -3
- package/dist/{chunk-PYUTATUY.js.map → chunk-C6PNF2OT.js.map} +1 -1
- package/dist/{chunk-VNEMV6IC.js → chunk-CFG6PGUZ.js} +4 -4
- package/dist/{chunk-VNEMV6IC.js.map → chunk-CFG6PGUZ.js.map} +1 -1
- package/dist/{chunk-GN7V2QHO.js → chunk-DHKZCR6U.js} +6 -6
- package/dist/{chunk-GN7V2QHO.js.map → chunk-DHKZCR6U.js.map} +1 -1
- package/dist/{chunk-WU5Z4JGX.js → chunk-DMGSEY7F.js} +3 -3
- package/dist/{chunk-WU5Z4JGX.js.map → chunk-DMGSEY7F.js.map} +1 -1
- package/dist/{chunk-VV7MDVGS.js → chunk-EF3PLLLA.js} +8 -8
- package/dist/{chunk-VV7MDVGS.js.map → chunk-EF3PLLLA.js.map} +1 -1
- package/dist/{chunk-WQPG22DY.js → chunk-EGI7F57E.js} +3 -3
- package/dist/{chunk-WQPG22DY.js.map → chunk-EGI7F57E.js.map} +1 -1
- package/dist/{chunk-W6KPVZZR.js → chunk-F7S2QA3D.js} +7 -7
- package/dist/{chunk-W6KPVZZR.js.map → chunk-F7S2QA3D.js.map} +1 -1
- package/dist/{chunk-P3WHN7JA.js → chunk-FTH3XLIN.js} +3 -3
- package/dist/{chunk-P3WHN7JA.js.map → chunk-FTH3XLIN.js.map} +1 -1
- package/dist/{chunk-CRO7DXS3.js → chunk-FXW6H6J3.js} +3 -3
- package/dist/{chunk-CRO7DXS3.js.map → chunk-FXW6H6J3.js.map} +1 -1
- package/dist/{chunk-TF6HFXTW.js → chunk-H7LRGY7U.js} +3 -3
- package/dist/{chunk-TF6HFXTW.js.map → chunk-H7LRGY7U.js.map} +1 -1
- package/dist/{chunk-RWAOBMAK.js → chunk-HZWTDQVJ.js} +6 -6
- package/dist/{chunk-RWAOBMAK.js.map → chunk-HZWTDQVJ.js.map} +1 -1
- package/dist/{chunk-HOJ5E2PG.js → chunk-IHOUADLX.js} +3 -3
- package/dist/{chunk-HOJ5E2PG.js.map → chunk-IHOUADLX.js.map} +1 -1
- package/dist/{chunk-GUODUINX.js → chunk-JOHFXU4C.js} +5 -5
- package/dist/{chunk-GUODUINX.js.map → chunk-JOHFXU4C.js.map} +1 -1
- package/dist/{chunk-MZ4LTJQD.js → chunk-K4YRFOFA.js} +7 -7
- package/dist/{chunk-MZ4LTJQD.js.map → chunk-K4YRFOFA.js.map} +1 -1
- package/dist/{chunk-LFHYQ6AN.js → chunk-M5WTY3EH.js} +3 -3
- package/dist/{chunk-LFHYQ6AN.js.map → chunk-M5WTY3EH.js.map} +1 -1
- package/dist/{chunk-RYGEIQWO.js → chunk-MGG4XAJ5.js} +3 -3
- package/dist/{chunk-RYGEIQWO.js.map → chunk-MGG4XAJ5.js.map} +1 -1
- package/dist/{chunk-O7OFWC34.js → chunk-O6RZ6AWT.js} +4 -4
- package/dist/{chunk-O7OFWC34.js.map → chunk-O6RZ6AWT.js.map} +1 -1
- package/dist/{chunk-LVUH4FOB.js → chunk-PBT52UWY.js} +5 -5
- package/dist/{chunk-LVUH4FOB.js.map → chunk-PBT52UWY.js.map} +1 -1
- package/dist/{chunk-C6WYORKW.js → chunk-PCYZMJUC.js} +3 -3
- package/dist/{chunk-C6WYORKW.js.map → chunk-PCYZMJUC.js.map} +1 -1
- package/dist/{chunk-ODP2N7CD.js → chunk-QBVXQHVJ.js} +4 -4
- package/dist/{chunk-ODP2N7CD.js.map → chunk-QBVXQHVJ.js.map} +1 -1
- package/dist/{chunk-MWYKP7CI.js → chunk-QMWP2ZP6.js} +3 -3
- package/dist/{chunk-MWYKP7CI.js.map → chunk-QMWP2ZP6.js.map} +1 -1
- package/dist/{chunk-LNTLWEYI.js → chunk-QXWCIK6D.js} +4 -4
- package/dist/{chunk-LNTLWEYI.js.map → chunk-QXWCIK6D.js.map} +1 -1
- package/dist/{chunk-5UWRPWK2.js → chunk-R7VWIXFX.js} +3 -3
- package/dist/{chunk-5UWRPWK2.js.map → chunk-R7VWIXFX.js.map} +1 -1
- package/dist/{chunk-Q7E4TNN7.js → chunk-SLBO4SEE.js} +3 -3
- package/dist/{chunk-Q7E4TNN7.js.map → chunk-SLBO4SEE.js.map} +1 -1
- package/dist/{chunk-FXVII733.js → chunk-T2752RH7.js} +27 -3
- package/dist/chunk-T2752RH7.js.map +1 -0
- package/dist/{chunk-4L5RHZHJ.js → chunk-T2O2IQJQ.js} +4 -4
- package/dist/{chunk-4L5RHZHJ.js.map → chunk-T2O2IQJQ.js.map} +1 -1
- package/dist/{chunk-YVQXIZY7.js → chunk-TQQN5AE2.js} +6 -6
- package/dist/{chunk-YVQXIZY7.js.map → chunk-TQQN5AE2.js.map} +1 -1
- package/dist/{chunk-3KTDODC5.js → chunk-VDY3VY7S.js} +3 -3
- package/dist/{chunk-3KTDODC5.js.map → chunk-VDY3VY7S.js.map} +1 -1
- package/dist/{chunk-2ZR562TA.js → chunk-VEVFVWF3.js} +5 -5
- package/dist/{chunk-2ZR562TA.js.map → chunk-VEVFVWF3.js.map} +1 -1
- package/dist/{chunk-W5LVGFHX.js → chunk-VNHYMLGK.js} +6 -6
- package/dist/{chunk-W5LVGFHX.js.map → chunk-VNHYMLGK.js.map} +1 -1
- package/dist/{chunk-MDU7ERR3.js → chunk-VQO4TTPE.js} +4 -4
- package/dist/{chunk-MDU7ERR3.js.map → chunk-VQO4TTPE.js.map} +1 -1
- package/dist/{chunk-JYPIPQ3V.js → chunk-X6WDFQYL.js} +3 -3
- package/dist/{chunk-JYPIPQ3V.js.map → chunk-X6WDFQYL.js.map} +1 -1
- package/dist/{chunk-NHA4SBKG.js → chunk-XMRNYUQY.js} +3 -3
- package/dist/{chunk-NHA4SBKG.js.map → chunk-XMRNYUQY.js.map} +1 -1
- package/dist/{chunk-6JH4QYKT.js → chunk-YDRURQ2W.js} +4 -4
- package/dist/{chunk-6JH4QYKT.js.map → chunk-YDRURQ2W.js.map} +1 -1
- package/dist/{chunk-AD4QPYNG.js → chunk-YEBA44IV.js} +4 -4
- package/dist/{chunk-AD4QPYNG.js.map → chunk-YEBA44IV.js.map} +1 -1
- package/dist/{chunk-V46O3Z7J.js → chunk-Z4EQHB26.js} +5 -5
- package/dist/{chunk-V46O3Z7J.js.map → chunk-Z4EQHB26.js.map} +1 -1
- package/dist/{chunk-TAVF4E7T.js → chunk-ZSEECSDV.js} +8 -8
- package/dist/{chunk-TAVF4E7T.js.map → chunk-ZSEECSDV.js.map} +1 -1
- package/dist/components/cart/index.js +1 -1
- package/dist/components/common/index.js +1 -1
- package/dist/components/drawer/index.js +23 -23
- package/dist/components/home/index.js +28 -28
- package/dist/components/layout/index.js +6 -6
- package/dist/components/product/index.js +25 -25
- package/dist/components/store/index.js +24 -24
- package/dist/components/toast/index.js +4 -4
- package/dist/dev/editor/index.js +2 -2
- package/dist/dev/index.js +2 -2
- package/dist/document-class-SWL4NCC6.js +32 -0
- package/dist/{document-class-TRLFCQHJ.js.map → document-class-SWL4NCC6.js.map} +1 -1
- package/dist/hooks/index.js +23 -23
- package/dist/hooks/useComments.js +3 -3
- package/dist/hooks/useGtm.js +23 -23
- package/dist/hooks/useMoney.js +23 -23
- package/dist/hooks/useProduct.js +3 -3
- package/dist/hooks/useStore.js +23 -23
- package/dist/hooks/useUser.js +5 -5
- package/dist/hooks/useWishlist.js +3 -3
- package/dist/index.js +23 -23
- package/dist/native-app/index.js +3 -3
- package/dist/{navigation-HWFEKUG6.js → navigation-7V4CSVG5.js} +8 -8
- package/dist/{navigation-HWFEKUG6.js.map → navigation-7V4CSVG5.js.map} +1 -1
- package/dist/{navigation-E75N4EU3.js → navigation-VMR4V27L.js} +7 -7
- package/dist/{navigation-E75N4EU3.js.map → navigation-VMR4V27L.js.map} +1 -1
- package/dist/{not-found-7SZU5K7G.js → not-found-S33EUV2Q.js} +26 -26
- package/dist/{not-found-7SZU5K7G.js.map → not-found-S33EUV2Q.js.map} +1 -1
- package/dist/providers/index.js +23 -23
- package/dist/routes/account/orders.js +8 -8
- package/dist/routes/account.js +17 -17
- package/dist/routes/blog/loader.d.ts.map +1 -1
- package/dist/routes/blog.js +27 -19
- package/dist/routes/blog.js.map +1 -1
- package/dist/routes/brands.js +8 -8
- package/dist/routes/cart.js +32 -32
- package/dist/routes/home.js +29 -29
- package/dist/routes/index.js +6 -6
- package/dist/routes/loyalty.js +9 -9
- package/dist/routes/page.js +8 -8
- package/dist/routes/product-listing.js +30 -30
- package/dist/routes/product.js +28 -28
- package/dist/routes/root/beforeLoad.d.ts.map +1 -1
- package/dist/routes/seo-redirects.js +6 -6
- package/dist/routes/testimonials.js +4 -4
- package/dist/routes/thank-you.js +8 -8
- package/dist/skeleton.js +29 -29
- package/dist/{store-lookup-LGYGZ4PU.js → store-lookup-D5C2LNXK.js} +11 -11
- package/dist/{store-lookup-LGYGZ4PU.js.map → store-lookup-D5C2LNXK.js.map} +1 -1
- package/dist/tanstack.js +19 -19
- package/dist/types/index.d.ts +5 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/baseHead.js +2 -2
- package/dist/utils/index.js +6 -6
- package/dist/utils/store-base.d.ts +30 -0
- package/dist/utils/store-base.d.ts.map +1 -1
- package/dist/utils/store-identity.d.ts +8 -0
- package/dist/utils/store-identity.d.ts.map +1 -1
- package/dist/vite/index.js +3 -3
- package/package.json +1 -1
- package/tailwind/routes/blog/loader.ts.txt +26 -8
- package/tailwind/routes/root/beforeLoad.ts.txt +27 -9
- package/dist/chunk-FXVII733.js.map +0 -1
- package/dist/chunk-S4KV6QGP.js.map +0 -1
- package/dist/document-class-TRLFCQHJ.js +0 -32
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/providers/NavigationProvider.ts"],"names":[],"mappings":"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","file":"chunk-2ZR562TA.js","sourcesContent":["import {\n createElement,\n createContext,\n useContext,\n useCallback,\n useRef,\n useEffect,\n useSyncExternalStore,\n type ReactNode,\n} from 'react';\nimport { useTwilight } from './twilight-context';\nimport { getTwilightContext, subscribeTwilight, type TwilightLocation } from '../twilight/context';\nimport { RouteId } from '../router/route-ids';\nimport { withoutStoreUrlBase } from '../utils/store-base';\nimport { extractScopeFromUrl } from '../utils/cookies';\nimport { getActiveScope } from '../api/client';\nimport { openNativeBrowser } from '../native-app';\nimport { SUPPORTED_LOCALES } from './locale-constants';\n\n// Re-export RouteId from centralized location\nexport { RouteId } from '../router/route-ids';\nexport type { RouteIdType } from '../router/route-ids';\n\n// Re-export TwilightLocation as Location for convenience\nexport type { TwilightLocation as Location } from '../twilight/context';\n\nexport type NavigateOptions = { replace?: boolean };\nexport type NavigateFn = (to: string, opts?: NavigateOptions) => void;\n\n/** Redirect error - thrown to trigger a redirect */\nexport class RedirectError extends Error {\n constructor(\n public path: string,\n public replace = false\n ) {\n super(`Redirect to ${path}`);\n this.name = 'RedirectError';\n }\n}\n\n/** NotFound error - thrown to trigger 404 */\nexport class NotFoundError extends Error {\n constructor(message?: string) {\n super(message ?? 'Not Found');\n this.name = 'NotFoundError';\n }\n}\n\n/** Unauthorized error - thrown to trigger 401 */\nexport class UnauthorizedError extends Error {\n constructor(message?: string) {\n super(message ?? 'Unauthorized');\n this.name = 'UnauthorizedError';\n }\n}\n\nexport { SettingsError } from '../utils/errors';\n\nexport const defaultNavigate: NavigateFn = (to, opts) => {\n if (opts?.replace) window.location.replace(to);\n else window.location.href = to;\n};\n\nexport interface RedirectOptions {\n replace?: boolean;\n /** HTTP status of a server redirect, e.g. 301 for a URL that moved for good. Defaults to 307. */\n statusCode?: number;\n}\n\n/** Default redirect - throws RedirectError with browser navigation as fallback */\nexport const defaultRedirect = (path: string, opts?: RedirectOptions): never => {\n const replace = opts?.replace ?? false;\n\n // In browser, perform actual navigation before throwing\n if (typeof window !== 'undefined') {\n if (replace) window.location.replace(path);\n else window.location.href = path;\n }\n\n throw new RedirectError(path, replace);\n};\n\n/** Default notFound - throws generic error */\nexport const defaultNotFound = (message?: string): never => {\n throw new NotFoundError(message);\n};\n\n/** Default unauthorized - throws generic error */\nexport const defaultUnauthorized = (message?: string): never => {\n throw new UnauthorizedError(message);\n};\n\n// ─── Framework-agnostic functions for loaders (outside React context) ──────\n\ninterface NavigationHandlers {\n notFound: (message?: string) => never;\n redirect: (path: string, opts?: RedirectOptions) => never;\n unauthorized: (message?: string) => never;\n}\n\n// One set per isolate, so a loader in another copy of this module (a separate\n// package entry, a dev reload) still throws what the framework adapter configured.\nconst HANDLERS_KEY = Symbol.for('salla.twilight.navigation.handlers');\nconst registry = globalThis as { [HANDLERS_KEY]?: NavigationHandlers };\nconst handlers: NavigationHandlers = (registry[HANDLERS_KEY] ??= {\n notFound: defaultNotFound,\n redirect: defaultRedirect,\n unauthorized: defaultUnauthorized,\n});\n\n/**\n * Throw a notFound error. Use in route loaders.\n * Framework adapters will override this to throw framework-specific errors.\n *\n * @example\n * ```ts\n * // In loader\n * import { notFound } from '@salla.sa/twilight-theme-engine/providers';\n *\n * if (!data) throw notFound();\n * ```\n */\nexport function notFound(message?: string): never {\n return handlers.notFound(message);\n}\n\n/**\n * Throw an unauthorized error. Use in route loaders to protect authenticated routes.\n * Framework adapters will override this to throw framework-specific errors.\n *\n * @example\n * ```ts\n * import { unauthorized } from '@salla.sa/twilight-theme-engine/providers';\n *\n * if (!user) throw unauthorized();\n * ```\n */\nexport function unauthorized(message?: string): never {\n return handlers.unauthorized(message);\n}\n\n/**\n * Throw a redirect. Use in route loaders.\n * Framework adapters will override this to throw framework-specific redirects.\n *\n * @param path - Path to redirect to\n * @param opts - Redirect options\n *\n * @example\n * ```ts\n * // In loader\n * import { redirect } from '@salla.sa/twilight-theme-engine/providers';\n *\n * throw redirect('/ar/cart');\n * ```\n */\nexport function redirect(path: string, opts?: RedirectOptions): never {\n return handlers.redirect(path, opts);\n}\n\n/**\n * Configure navigation functions for a specific framework.\n * Called by framework adapters during setup.\n */\nexport function configureNavigation(config: {\n notFound?: (message?: string) => never;\n redirect?: (path: string, opts?: RedirectOptions) => never;\n unauthorized?: (_message?: string) => never;\n}): void {\n if (config.notFound) handlers.notFound = config.notFound;\n if (config.redirect) handlers.redirect = config.redirect;\n if (config.unauthorized) handlers.unauthorized = config.unauthorized;\n}\n\n// ─── Loader Error Handling Helpers ─────────────────────────────────────────────\n\n/**\n * Wraps an API promise with error handling for route loaders.\n * On a 404/410 response throws notFound(); other errors propagate.\n *\n * @example\n * ```ts\n * findOrThrow: (id, locale) => orThrow(product.find(id, locale)),\n * const data = await product.findOrThrow(id, locale);\n * ```\n */\nexport async function orThrow<T>(promise: Promise<T>): Promise<T> {\n try {\n return await promise;\n } catch (error) {\n console.debug('[loader error]', error);\n if (isMissingResource(error)) return notFound();\n throw error;\n }\n}\n\n/** The HTTP status an API error carries, if it is one. */\nexport function responseStatusOf(error: unknown): number | undefined {\n const status = (error as { response?: { status?: unknown } } | null)?.response?.status;\n return typeof status === 'number' ? status : undefined;\n}\n\n/** The API answers a missing resource with 410, sometimes 404. */\nexport function isMissingResource(error: unknown): boolean {\n const status = responseStatusOf(error);\n return status === 404 || status === 410;\n}\n\n/**\n * Wraps an API promise with error handling for authenticated route loaders.\n * On a 401/403 response throws unauthorized(); other errors propagate.\n *\n * @example\n * ```ts\n * const data = await orUnauthorized(order.find(id, locale));\n * ```\n */\nexport async function orUnauthorized<T>(promise: Promise<T>): Promise<T> {\n try {\n return await promise;\n } catch (error) {\n const status = (error as unknown as { response?: { status?: number } })?.response?.status;\n if (status === 401 || status === 403) {\n throw unauthorized();\n }\n throw error;\n }\n}\n\n// ─── Navigation Context ──────────────────────────────────────────────────────\n\ninterface NavigationContextValue {\n navigate: NavigateFn;\n}\n\nconst NavigationContext = createContext<NavigationContextValue>({\n navigate: defaultNavigate,\n});\n\nexport function NavigationProvider({\n navigate,\n children,\n}: {\n navigate: NavigateFn;\n children: ReactNode;\n}) {\n return createElement(NavigationContext.Provider, { value: { navigate } }, children);\n}\n\n// ─── Primary Hooks (High Compatibility) ───────────────────────────────────────\n\n/**\n * Get the navigate function.\n * Matches React Router, TanStack Router, and Remix naming convention.\n *\n * @returns Navigate function\n *\n * @example\n * ```tsx\n * const navigate = useNavigate();\n * navigate('/cart');\n * navigate('/cart', { replace: true });\n * ```\n */\nexport function useNavigate(): NavigateFn {\n return useContext(NavigationContext).navigate;\n}\n\n/**\n * Get the current route ID.\n * Used for route detection (isHome, isProduct, etc.)\n *\n * @returns Current route ID string\n *\n * @example\n * ```tsx\n * const routeId = useRouteId();\n * if (routeId === RouteId.INDEX) { ... }\n * ```\n */\nexport function useRouteId(): string {\n return useSyncExternalStore(\n subscribeTwilight,\n () => getTwilightContext().routeId,\n () => getTwilightContext().routeId\n );\n}\n\n/**\n * Get the current location (TanStack Router compatible).\n * Reads from the router context for SSR compatibility.\n *\n * @returns Location object matching TanStack's ParsedLocation\n *\n * @example\n * ```tsx\n * const location = useLocation();\n * console.log(location.pathname); // '/ar/products'\n * console.log(location.searchStr); // '?q=shoes&page=2'\n * console.log(location.search); // { q: 'shoes', page: '2' }\n * console.log(location.href); // 'https://store.com/ar/products?q=shoes'\n * console.log(location.hash); // '#section-1'\n * console.log(location.state); // { scrollY: 100 }\n * ```\n */\nexport function useLocation<TSearch = Record<string, unknown>>(): TwilightLocation<TSearch> {\n useTwilight();\n return getTwilightContext().location as TwilightLocation<TSearch>;\n}\n\n// ─── Selector Hooks ───────────────────────────────────────────────────────────\n\n/**\n * Check if current page is homepage */\nexport function useIsHome(): boolean {\n return useRouteId() === RouteId.INDEX;\n}\n\n/** Check if current page is product detail */\nexport function useIsProduct(): boolean {\n return useRouteId() === RouteId.PRODUCT_SINGLE;\n}\n\n/** Check if current page is cart */\nexport function useIsCart(): boolean {\n return useRouteId() === RouteId.CART;\n}\n\n/** Check if current page is in customer area */\nexport function useIsCustomer(): boolean {\n return useRouteId().startsWith('customer');\n}\n\n/** Check if current page is blog related */\nexport function useIsBlog(): boolean {\n const routeId = useRouteId();\n return routeId === RouteId.BLOG_INDEX || routeId === RouteId.BLOG_SINGLE;\n}\n\n/** Check if current page is brands related */\nexport function useIsBrands(): boolean {\n const routeId = useRouteId();\n return routeId === RouteId.BRANDS_INDEX || routeId === RouteId.BRANDS_SINGLE;\n}\n\n/** Check if current page is search */\nexport function useIsSearch(): boolean {\n return useRouteId() === RouteId.SEARCH;\n}\n\n// ─── Navigation Interceptor ──────────────────────────────────────────────────\n\n/**\n * NavigationInterceptor - Framework-agnostic SPA navigation interceptor.\n *\n * Uses navigate function from NavigationProvider context and store URL\n * from TwilightProvider to intercept same-origin navigations.\n */\nexport function NavigationInterceptor(): null {\n const navigate = useNavigate();\n const { store } = useTwilight();\n useNavigationInterceptor(navigate, store?.url, store?.username);\n return null;\n}\n\n/**\n * resolveRelativePath - Resolve href to store-relative path\n *\n * Returns `null` when the URL is not on the same origin as the store,\n * keeping this helper safe against open-redirect misuse.\n *\n * The path is the application's, not the address on Salla's host: a store served\n * under its username there (`https://demostore.salla.sa/ar/dev-…/`) hands out links\n * carrying that segment, and it is removed. On a host where the store is the root\n * of every URL, the router adds its own segment back when it navigates.\n *\n * @param href - The URL to resolve\n * @param storeUrl - The store's base URL\n * @param username - The store's username, which tells that segment apart from a\n * locale spelled the same way (see `withoutStoreUrlBase`)\n * @returns The relative path string, or null if the URL is external\n */\nexport function resolveRelativePath(\n href: string,\n storeUrl: string,\n username?: string | null\n): string | null {\n try {\n const target = new URL(href, window.location.href);\n const base = new URL(storeUrl);\n\n if (target.origin !== base.origin) return null;\n\n const pathname = withoutStoreUrlBase(target.pathname, base.pathname, username);\n const path = pathname + target.search + target.hash;\n return path || '/';\n } catch {\n return null;\n }\n}\n\n/**\n * Pages the Store app renders, not the theme: checkout, payment, digital orders, a\n * gift's page, the booking page (`cart/booking/<id>`, where \"book now\" leads), the\n * SDK's auth endpoints, and the order invoice. The storefront dispatcher sends a\n * document request for them to the app (`bypass.ts` in store-front-dispacher), so\n * only a page load reaches them; rendered in place, the router has no route and\n * shows its 404. Keep in step with the dispatcher's list.\n */\nconst APP_PATH_PREFIXES = [\n '/checkout',\n '/payment',\n '/orders/digital',\n '/gifts',\n '/cart/booking',\n '/auth/jwt',\n '/auth/refresh',\n];\nconst APP_PATH_PATTERNS = [/^\\/account\\/orders\\/[^/]+\\/print\\/?$/];\n\n/** Whether a store-relative path (`/ar/cart/booking/1?x`) is one of the app's pages. */\nexport function isAppPath(path: string): boolean {\n let pathname = path.split(/[?#]/)[0];\n const first = pathname.split('/')[1];\n if ((SUPPORTED_LOCALES as readonly string[]).includes(first)) {\n pathname = pathname.slice(first.length + 1) || '/';\n }\n return (\n APP_PATH_PREFIXES.some((prefix) => pathname === prefix || pathname.startsWith(`${prefix}/`)) ||\n APP_PATH_PATTERNS.some((pattern) => pattern.test(pathname))\n );\n}\n\n/**\n * EXTERNAL_TARGETS - Target attribute values that indicate external navigation\n */\nconst EXTERNAL_TARGETS = new Set(['_blank', '_parent', '_top']);\n\n/**\n * shouldIntercept - Determine if an anchor click should be intercepted by SPA router\n *\n * Follows browser conventions: modifier keys, external targets, downloads,\n * and non-HTTP(S) protocols are left to the browser's default behavior.\n *\n * @param anchor - The anchor element that was clicked\n * @param event - The click event\n * @returns true if the click should be intercepted by the router\n */\nexport function shouldIntercept(anchor: HTMLAnchorElement, event: MouseEvent): boolean {\n if (event.defaultPrevented) return false;\n\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return false;\n\n const targetAttr = anchor.getAttribute('target');\n if (targetAttr && EXTERNAL_TARGETS.has(targetAttr)) return false;\n\n if (anchor.hasAttribute('download')) return false;\n\n const rel = (anchor.getAttribute('rel') ?? '').split(/\\s+/);\n if (rel.includes('external')) return false;\n\n const href = anchor.getAttribute('href') ?? '';\n if (!href) return false;\n\n try {\n const url = new URL(href, window.location.href);\n if (url.protocol.startsWith('javascript:')) return false;\n } catch {\n return false;\n }\n\n return true;\n}\n\n/**\n * Whether `href` switches market: its `?scope=` names another scope than the active one,\n * or the same scope with another branch (`allocation_type` / `allocation_id`).\n *\n * Twig switches market with a full load (the SDK's scopes modal calls\n * `location.replace('?scope=<id>')`), and only a document request lets the server render\n * the new market and record it in the `scope` cookie. Left to the browser, not the router.\n */\nexport function switchesScope(href: string): boolean {\n let url: URL;\n try {\n url = new URL(href, window.location.href);\n } catch {\n return false;\n }\n const requested = extractScopeFromUrl(url.href);\n if (!requested) return false;\n const active = getActiveScope();\n if (requested.id !== active?.id) return true;\n return (\n requested.allocation_id != null &&\n (requested.allocation_id !== active.allocation_id ||\n requested.allocation_type !== active.allocation_type)\n );\n}\n\n/**\n * Whether an untouched tap on `anchor` would load a page off the store: an\n * http(s) link to neither this page's origin nor the store's. `mailto:`, `tel:`\n * and the like are the device's to handle, and are left alone. So are product\n * gallery slides (`data-fslightbox`): each links to its own image or video, and\n * the gallery opens it in the app's native gallery, from a click handler that\n * runs after this capture-phase check, so `event.defaultPrevented` is still false.\n */\nexport function leavesStore(\n anchor: HTMLAnchorElement,\n event: MouseEvent,\n storeUrl: string | undefined\n): boolean {\n if (event.defaultPrevented || anchor.hasAttribute('download')) return false;\n if (anchor.hasAttribute('data-fslightbox')) return false;\n let url: URL;\n try {\n url = new URL(anchor.getAttribute('href') ?? '', window.location.href);\n } catch {\n return false;\n }\n if (url.protocol !== 'http:' && url.protocol !== 'https:') return false;\n if (url.origin === window.location.origin) return false;\n try {\n return !storeUrl || url.origin !== new URL(storeUrl).origin;\n } catch {\n return true;\n }\n}\n\nfunction isSamePage(href: string): boolean {\n const url = new URL(href, window.location.href);\n return url.pathname === window.location.pathname && url.search === window.location.search;\n}\n\nfunction closeEnclosingModal(path: EventTarget[]): void {\n const modal = path.find(\n (el): el is HTMLElement & { close?: () => unknown } =>\n el instanceof HTMLElement && el.localName === 'salla-modal'\n );\n void modal?.close?.();\n}\n\n// ─── Navigation Interceptor Hook (framework-agnostic) ─────────────────────────\n\n/**\n * Hook for navigation interception using framework-agnostic navigate function.\n * Framework adapters call this with their navigate implementation.\n */\nexport function useNavigationInterceptor(\n navigate: NavigateFn,\n storeUrl: string | undefined,\n username?: string\n): void {\n const storeUrlRef = useRef<string | undefined>(storeUrl);\n const usernameRef = useRef<string | undefined>(username);\n\n useEffect(() => {\n storeUrlRef.current = storeUrl;\n usernameRef.current = username;\n }, [storeUrl, username]);\n\n const tryNavigate = useCallback(\n (href: string, replace = false): boolean => {\n const currentStoreUrl = storeUrlRef.current;\n if (!currentStoreUrl || switchesScope(href)) return false;\n\n const relativePath = resolveRelativePath(href, currentStoreUrl, usernameRef.current);\n // The app's pages are left to the browser: only a page load reaches the app.\n if (!relativePath || isAppPath(relativePath)) return false;\n\n navigate(relativePath, { replace });\n return true;\n },\n [navigate]\n );\n\n useEffect(() => {\n // ── Pointer movement tracking ────────────────────────────────────────────\n // Detect drag/scroll gestures to avoid intercepting clicks from swipes.\n let pointerStartX = 0;\n let pointerStartY = 0;\n let pointerSwiped = false;\n const MOVE_THRESHOLD = 10;\n\n function handlePointerDown(event: PointerEvent): void {\n pointerStartX = event.clientX;\n pointerStartY = event.clientY;\n pointerSwiped = false;\n }\n\n function handlePointerUp(event: PointerEvent): void {\n const dx = Math.abs(event.clientX - pointerStartX);\n const dy = Math.abs(event.clientY - pointerStartY);\n pointerSwiped = dx > MOVE_THRESHOLD || dy > MOVE_THRESHOLD;\n }\n\n // ── Anchor click interception ────────────────────────────────────────────\n function handleClick(event: MouseEvent): void {\n // Ignore clicks that resulted from swipe/drag gestures.\n if (pointerSwiped) {\n pointerSwiped = false;\n return;\n }\n\n const path = event.composedPath();\n const anchor = path.find((el): el is HTMLAnchorElement => el instanceof HTMLAnchorElement);\n\n // Inside the Salla app, a link that leaves the store opens in the device's\n // browser; loaded in the app's webview it would strand the shopper there.\n if (\n anchor &&\n leavesStore(anchor, event, storeUrlRef.current) &&\n openNativeBrowser(anchor.href)\n ) {\n event.preventDefault();\n return;\n }\n\n if (!anchor || !shouldIntercept(anchor, event)) return;\n\n const samePage = isSamePage(anchor.href);\n if (tryNavigate(anchor.href, false)) {\n event.preventDefault();\n // A page load would close a web component's modal; an in-app navigation leaves it open.\n if (!samePage) closeEnclosingModal(path);\n }\n }\n\n // ── window.location.assign patch ─────────────────────────────────────────\n const origAssign = window.location.assign;\n function patchedAssign(url: string): void {\n if (!tryNavigate(url, false)) origAssign.call(window.location, url);\n }\n\n // ── window.location.replace patch ────────────────────────────────────────\n const origReplace = window.location.replace;\n function patchedReplace(url: string): void {\n if (!tryNavigate(url, true)) origReplace.call(window.location, url);\n }\n\n let assignPatched = false;\n let replacePatched = false;\n try {\n window.location.assign = patchedAssign;\n assignPatched = true;\n } catch {\n /* non-writable in this environment */\n }\n try {\n window.location.replace = patchedReplace;\n replacePatched = true;\n } catch {\n /* non-writable in this environment */\n }\n\n document.addEventListener('click', handleClick, { capture: true });\n document.addEventListener('pointerdown', handlePointerDown, { passive: true });\n document.addEventListener('pointerup', handlePointerUp, { passive: true });\n\n return () => {\n document.removeEventListener('click', handleClick, { capture: true });\n document.removeEventListener('pointerdown', handlePointerDown);\n document.removeEventListener('pointerup', handlePointerUp);\n if (assignPatched) {\n try {\n window.location.assign = origAssign;\n } catch {\n /* ignore */\n }\n }\n if (replacePatched) {\n try {\n window.location.replace = origReplace;\n } catch {\n /* ignore */\n }\n }\n };\n }, [tryNavigate]);\n}\n\n// ─── Client navigation config ─────────────────────────────────────────────────\n\nexport interface ClientNav {\n /** Framework adapter to use for client-side navigation. @default 'tanstack' */\n framework?: 'tanstack' | 'nextjs';\n /**\n * Intercept same-origin `<a>` clicks and `window.location` calls from web\n * components and route them through the framework router.\n * @default true\n */\n interceptLinks?: boolean;\n}\n\n// Framework adapter setups are registered in navigation-setups.ts to avoid circular imports.\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/providers/NavigationProvider.ts"],"names":[],"mappings":"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","file":"chunk-VEVFVWF3.js","sourcesContent":["import {\n createElement,\n createContext,\n useContext,\n useCallback,\n useRef,\n useEffect,\n useSyncExternalStore,\n type ReactNode,\n} from 'react';\nimport { useTwilight } from './twilight-context';\nimport { getTwilightContext, subscribeTwilight, type TwilightLocation } from '../twilight/context';\nimport { RouteId } from '../router/route-ids';\nimport { withoutStoreUrlBase } from '../utils/store-base';\nimport { extractScopeFromUrl } from '../utils/cookies';\nimport { getActiveScope } from '../api/client';\nimport { openNativeBrowser } from '../native-app';\nimport { SUPPORTED_LOCALES } from './locale-constants';\n\n// Re-export RouteId from centralized location\nexport { RouteId } from '../router/route-ids';\nexport type { RouteIdType } from '../router/route-ids';\n\n// Re-export TwilightLocation as Location for convenience\nexport type { TwilightLocation as Location } from '../twilight/context';\n\nexport type NavigateOptions = { replace?: boolean };\nexport type NavigateFn = (to: string, opts?: NavigateOptions) => void;\n\n/** Redirect error - thrown to trigger a redirect */\nexport class RedirectError extends Error {\n constructor(\n public path: string,\n public replace = false\n ) {\n super(`Redirect to ${path}`);\n this.name = 'RedirectError';\n }\n}\n\n/** NotFound error - thrown to trigger 404 */\nexport class NotFoundError extends Error {\n constructor(message?: string) {\n super(message ?? 'Not Found');\n this.name = 'NotFoundError';\n }\n}\n\n/** Unauthorized error - thrown to trigger 401 */\nexport class UnauthorizedError extends Error {\n constructor(message?: string) {\n super(message ?? 'Unauthorized');\n this.name = 'UnauthorizedError';\n }\n}\n\nexport { SettingsError } from '../utils/errors';\n\nexport const defaultNavigate: NavigateFn = (to, opts) => {\n if (opts?.replace) window.location.replace(to);\n else window.location.href = to;\n};\n\nexport interface RedirectOptions {\n replace?: boolean;\n /** HTTP status of a server redirect, e.g. 301 for a URL that moved for good. Defaults to 307. */\n statusCode?: number;\n}\n\n/** Default redirect - throws RedirectError with browser navigation as fallback */\nexport const defaultRedirect = (path: string, opts?: RedirectOptions): never => {\n const replace = opts?.replace ?? false;\n\n // In browser, perform actual navigation before throwing\n if (typeof window !== 'undefined') {\n if (replace) window.location.replace(path);\n else window.location.href = path;\n }\n\n throw new RedirectError(path, replace);\n};\n\n/** Default notFound - throws generic error */\nexport const defaultNotFound = (message?: string): never => {\n throw new NotFoundError(message);\n};\n\n/** Default unauthorized - throws generic error */\nexport const defaultUnauthorized = (message?: string): never => {\n throw new UnauthorizedError(message);\n};\n\n// ─── Framework-agnostic functions for loaders (outside React context) ──────\n\ninterface NavigationHandlers {\n notFound: (message?: string) => never;\n redirect: (path: string, opts?: RedirectOptions) => never;\n unauthorized: (message?: string) => never;\n}\n\n// One set per isolate, so a loader in another copy of this module (a separate\n// package entry, a dev reload) still throws what the framework adapter configured.\nconst HANDLERS_KEY = Symbol.for('salla.twilight.navigation.handlers');\nconst registry = globalThis as { [HANDLERS_KEY]?: NavigationHandlers };\nconst handlers: NavigationHandlers = (registry[HANDLERS_KEY] ??= {\n notFound: defaultNotFound,\n redirect: defaultRedirect,\n unauthorized: defaultUnauthorized,\n});\n\n/**\n * Throw a notFound error. Use in route loaders.\n * Framework adapters will override this to throw framework-specific errors.\n *\n * @example\n * ```ts\n * // In loader\n * import { notFound } from '@salla.sa/twilight-theme-engine/providers';\n *\n * if (!data) throw notFound();\n * ```\n */\nexport function notFound(message?: string): never {\n return handlers.notFound(message);\n}\n\n/**\n * Throw an unauthorized error. Use in route loaders to protect authenticated routes.\n * Framework adapters will override this to throw framework-specific errors.\n *\n * @example\n * ```ts\n * import { unauthorized } from '@salla.sa/twilight-theme-engine/providers';\n *\n * if (!user) throw unauthorized();\n * ```\n */\nexport function unauthorized(message?: string): never {\n return handlers.unauthorized(message);\n}\n\n/**\n * Throw a redirect. Use in route loaders.\n * Framework adapters will override this to throw framework-specific redirects.\n *\n * @param path - Path to redirect to\n * @param opts - Redirect options\n *\n * @example\n * ```ts\n * // In loader\n * import { redirect } from '@salla.sa/twilight-theme-engine/providers';\n *\n * throw redirect('/ar/cart');\n * ```\n */\nexport function redirect(path: string, opts?: RedirectOptions): never {\n return handlers.redirect(path, opts);\n}\n\n/**\n * Configure navigation functions for a specific framework.\n * Called by framework adapters during setup.\n */\nexport function configureNavigation(config: {\n notFound?: (message?: string) => never;\n redirect?: (path: string, opts?: RedirectOptions) => never;\n unauthorized?: (_message?: string) => never;\n}): void {\n if (config.notFound) handlers.notFound = config.notFound;\n if (config.redirect) handlers.redirect = config.redirect;\n if (config.unauthorized) handlers.unauthorized = config.unauthorized;\n}\n\n// ─── Loader Error Handling Helpers ─────────────────────────────────────────────\n\n/**\n * Wraps an API promise with error handling for route loaders.\n * On a 404/410 response throws notFound(); other errors propagate.\n *\n * @example\n * ```ts\n * findOrThrow: (id, locale) => orThrow(product.find(id, locale)),\n * const data = await product.findOrThrow(id, locale);\n * ```\n */\nexport async function orThrow<T>(promise: Promise<T>): Promise<T> {\n try {\n return await promise;\n } catch (error) {\n console.debug('[loader error]', error);\n if (isMissingResource(error)) return notFound();\n throw error;\n }\n}\n\n/** The HTTP status an API error carries, if it is one. */\nexport function responseStatusOf(error: unknown): number | undefined {\n const status = (error as { response?: { status?: unknown } } | null)?.response?.status;\n return typeof status === 'number' ? status : undefined;\n}\n\n/** The API answers a missing resource with 410, sometimes 404. */\nexport function isMissingResource(error: unknown): boolean {\n const status = responseStatusOf(error);\n return status === 404 || status === 410;\n}\n\n/**\n * Wraps an API promise with error handling for authenticated route loaders.\n * On a 401/403 response throws unauthorized(); other errors propagate.\n *\n * @example\n * ```ts\n * const data = await orUnauthorized(order.find(id, locale));\n * ```\n */\nexport async function orUnauthorized<T>(promise: Promise<T>): Promise<T> {\n try {\n return await promise;\n } catch (error) {\n const status = (error as unknown as { response?: { status?: number } })?.response?.status;\n if (status === 401 || status === 403) {\n throw unauthorized();\n }\n throw error;\n }\n}\n\n// ─── Navigation Context ──────────────────────────────────────────────────────\n\ninterface NavigationContextValue {\n navigate: NavigateFn;\n}\n\nconst NavigationContext = createContext<NavigationContextValue>({\n navigate: defaultNavigate,\n});\n\nexport function NavigationProvider({\n navigate,\n children,\n}: {\n navigate: NavigateFn;\n children: ReactNode;\n}) {\n return createElement(NavigationContext.Provider, { value: { navigate } }, children);\n}\n\n// ─── Primary Hooks (High Compatibility) ───────────────────────────────────────\n\n/**\n * Get the navigate function.\n * Matches React Router, TanStack Router, and Remix naming convention.\n *\n * @returns Navigate function\n *\n * @example\n * ```tsx\n * const navigate = useNavigate();\n * navigate('/cart');\n * navigate('/cart', { replace: true });\n * ```\n */\nexport function useNavigate(): NavigateFn {\n return useContext(NavigationContext).navigate;\n}\n\n/**\n * Get the current route ID.\n * Used for route detection (isHome, isProduct, etc.)\n *\n * @returns Current route ID string\n *\n * @example\n * ```tsx\n * const routeId = useRouteId();\n * if (routeId === RouteId.INDEX) { ... }\n * ```\n */\nexport function useRouteId(): string {\n return useSyncExternalStore(\n subscribeTwilight,\n () => getTwilightContext().routeId,\n () => getTwilightContext().routeId\n );\n}\n\n/**\n * Get the current location (TanStack Router compatible).\n * Reads from the router context for SSR compatibility.\n *\n * @returns Location object matching TanStack's ParsedLocation\n *\n * @example\n * ```tsx\n * const location = useLocation();\n * console.log(location.pathname); // '/ar/products'\n * console.log(location.searchStr); // '?q=shoes&page=2'\n * console.log(location.search); // { q: 'shoes', page: '2' }\n * console.log(location.href); // 'https://store.com/ar/products?q=shoes'\n * console.log(location.hash); // '#section-1'\n * console.log(location.state); // { scrollY: 100 }\n * ```\n */\nexport function useLocation<TSearch = Record<string, unknown>>(): TwilightLocation<TSearch> {\n useTwilight();\n return getTwilightContext().location as TwilightLocation<TSearch>;\n}\n\n// ─── Selector Hooks ───────────────────────────────────────────────────────────\n\n/**\n * Check if current page is homepage */\nexport function useIsHome(): boolean {\n return useRouteId() === RouteId.INDEX;\n}\n\n/** Check if current page is product detail */\nexport function useIsProduct(): boolean {\n return useRouteId() === RouteId.PRODUCT_SINGLE;\n}\n\n/** Check if current page is cart */\nexport function useIsCart(): boolean {\n return useRouteId() === RouteId.CART;\n}\n\n/** Check if current page is in customer area */\nexport function useIsCustomer(): boolean {\n return useRouteId().startsWith('customer');\n}\n\n/** Check if current page is blog related */\nexport function useIsBlog(): boolean {\n const routeId = useRouteId();\n return routeId === RouteId.BLOG_INDEX || routeId === RouteId.BLOG_SINGLE;\n}\n\n/** Check if current page is brands related */\nexport function useIsBrands(): boolean {\n const routeId = useRouteId();\n return routeId === RouteId.BRANDS_INDEX || routeId === RouteId.BRANDS_SINGLE;\n}\n\n/** Check if current page is search */\nexport function useIsSearch(): boolean {\n return useRouteId() === RouteId.SEARCH;\n}\n\n// ─── Navigation Interceptor ──────────────────────────────────────────────────\n\n/**\n * NavigationInterceptor - Framework-agnostic SPA navigation interceptor.\n *\n * Uses navigate function from NavigationProvider context and store URL\n * from TwilightProvider to intercept same-origin navigations.\n */\nexport function NavigationInterceptor(): null {\n const navigate = useNavigate();\n const { store } = useTwilight();\n useNavigationInterceptor(navigate, store?.url, store?.username);\n return null;\n}\n\n/**\n * resolveRelativePath - Resolve href to store-relative path\n *\n * Returns `null` when the URL is not on the same origin as the store,\n * keeping this helper safe against open-redirect misuse.\n *\n * The path is the application's, not the address on Salla's host: a store served\n * under its username there (`https://demostore.salla.sa/ar/dev-…/`) hands out links\n * carrying that segment, and it is removed. On a host where the store is the root\n * of every URL, the router adds its own segment back when it navigates.\n *\n * @param href - The URL to resolve\n * @param storeUrl - The store's base URL\n * @param username - The store's username, which tells that segment apart from a\n * locale spelled the same way (see `withoutStoreUrlBase`)\n * @returns The relative path string, or null if the URL is external\n */\nexport function resolveRelativePath(\n href: string,\n storeUrl: string,\n username?: string | null\n): string | null {\n try {\n const target = new URL(href, window.location.href);\n const base = new URL(storeUrl);\n\n if (target.origin !== base.origin) return null;\n\n const pathname = withoutStoreUrlBase(target.pathname, base.pathname, username);\n const path = pathname + target.search + target.hash;\n return path || '/';\n } catch {\n return null;\n }\n}\n\n/**\n * Pages the Store app renders, not the theme: checkout, payment, digital orders, a\n * gift's page, the booking page (`cart/booking/<id>`, where \"book now\" leads), the\n * SDK's auth endpoints, and the order invoice. The storefront dispatcher sends a\n * document request for them to the app (`bypass.ts` in store-front-dispacher), so\n * only a page load reaches them; rendered in place, the router has no route and\n * shows its 404. Keep in step with the dispatcher's list.\n */\nconst APP_PATH_PREFIXES = [\n '/checkout',\n '/payment',\n '/orders/digital',\n '/gifts',\n '/cart/booking',\n '/auth/jwt',\n '/auth/refresh',\n];\nconst APP_PATH_PATTERNS = [/^\\/account\\/orders\\/[^/]+\\/print\\/?$/];\n\n/** Whether a store-relative path (`/ar/cart/booking/1?x`) is one of the app's pages. */\nexport function isAppPath(path: string): boolean {\n let pathname = path.split(/[?#]/)[0];\n const first = pathname.split('/')[1];\n if ((SUPPORTED_LOCALES as readonly string[]).includes(first)) {\n pathname = pathname.slice(first.length + 1) || '/';\n }\n return (\n APP_PATH_PREFIXES.some((prefix) => pathname === prefix || pathname.startsWith(`${prefix}/`)) ||\n APP_PATH_PATTERNS.some((pattern) => pattern.test(pathname))\n );\n}\n\n/**\n * EXTERNAL_TARGETS - Target attribute values that indicate external navigation\n */\nconst EXTERNAL_TARGETS = new Set(['_blank', '_parent', '_top']);\n\n/**\n * shouldIntercept - Determine if an anchor click should be intercepted by SPA router\n *\n * Follows browser conventions: modifier keys, external targets, downloads,\n * and non-HTTP(S) protocols are left to the browser's default behavior.\n *\n * @param anchor - The anchor element that was clicked\n * @param event - The click event\n * @returns true if the click should be intercepted by the router\n */\nexport function shouldIntercept(anchor: HTMLAnchorElement, event: MouseEvent): boolean {\n if (event.defaultPrevented) return false;\n\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return false;\n\n const targetAttr = anchor.getAttribute('target');\n if (targetAttr && EXTERNAL_TARGETS.has(targetAttr)) return false;\n\n if (anchor.hasAttribute('download')) return false;\n\n const rel = (anchor.getAttribute('rel') ?? '').split(/\\s+/);\n if (rel.includes('external')) return false;\n\n const href = anchor.getAttribute('href') ?? '';\n if (!href) return false;\n\n try {\n const url = new URL(href, window.location.href);\n if (url.protocol.startsWith('javascript:')) return false;\n } catch {\n return false;\n }\n\n return true;\n}\n\n/**\n * Whether `href` switches market: its `?scope=` names another scope than the active one,\n * or the same scope with another branch (`allocation_type` / `allocation_id`).\n *\n * Twig switches market with a full load (the SDK's scopes modal calls\n * `location.replace('?scope=<id>')`), and only a document request lets the server render\n * the new market and record it in the `scope` cookie. Left to the browser, not the router.\n */\nexport function switchesScope(href: string): boolean {\n let url: URL;\n try {\n url = new URL(href, window.location.href);\n } catch {\n return false;\n }\n const requested = extractScopeFromUrl(url.href);\n if (!requested) return false;\n const active = getActiveScope();\n if (requested.id !== active?.id) return true;\n return (\n requested.allocation_id != null &&\n (requested.allocation_id !== active.allocation_id ||\n requested.allocation_type !== active.allocation_type)\n );\n}\n\n/**\n * Whether an untouched tap on `anchor` would load a page off the store: an\n * http(s) link to neither this page's origin nor the store's. `mailto:`, `tel:`\n * and the like are the device's to handle, and are left alone. So are product\n * gallery slides (`data-fslightbox`): each links to its own image or video, and\n * the gallery opens it in the app's native gallery, from a click handler that\n * runs after this capture-phase check, so `event.defaultPrevented` is still false.\n */\nexport function leavesStore(\n anchor: HTMLAnchorElement,\n event: MouseEvent,\n storeUrl: string | undefined\n): boolean {\n if (event.defaultPrevented || anchor.hasAttribute('download')) return false;\n if (anchor.hasAttribute('data-fslightbox')) return false;\n let url: URL;\n try {\n url = new URL(anchor.getAttribute('href') ?? '', window.location.href);\n } catch {\n return false;\n }\n if (url.protocol !== 'http:' && url.protocol !== 'https:') return false;\n if (url.origin === window.location.origin) return false;\n try {\n return !storeUrl || url.origin !== new URL(storeUrl).origin;\n } catch {\n return true;\n }\n}\n\nfunction isSamePage(href: string): boolean {\n const url = new URL(href, window.location.href);\n return url.pathname === window.location.pathname && url.search === window.location.search;\n}\n\nfunction closeEnclosingModal(path: EventTarget[]): void {\n const modal = path.find(\n (el): el is HTMLElement & { close?: () => unknown } =>\n el instanceof HTMLElement && el.localName === 'salla-modal'\n );\n void modal?.close?.();\n}\n\n// ─── Navigation Interceptor Hook (framework-agnostic) ─────────────────────────\n\n/**\n * Hook for navigation interception using framework-agnostic navigate function.\n * Framework adapters call this with their navigate implementation.\n */\nexport function useNavigationInterceptor(\n navigate: NavigateFn,\n storeUrl: string | undefined,\n username?: string\n): void {\n const storeUrlRef = useRef<string | undefined>(storeUrl);\n const usernameRef = useRef<string | undefined>(username);\n\n useEffect(() => {\n storeUrlRef.current = storeUrl;\n usernameRef.current = username;\n }, [storeUrl, username]);\n\n const tryNavigate = useCallback(\n (href: string, replace = false): boolean => {\n const currentStoreUrl = storeUrlRef.current;\n if (!currentStoreUrl || switchesScope(href)) return false;\n\n const relativePath = resolveRelativePath(href, currentStoreUrl, usernameRef.current);\n // The app's pages are left to the browser: only a page load reaches the app.\n if (!relativePath || isAppPath(relativePath)) return false;\n\n navigate(relativePath, { replace });\n return true;\n },\n [navigate]\n );\n\n useEffect(() => {\n // ── Pointer movement tracking ────────────────────────────────────────────\n // Detect drag/scroll gestures to avoid intercepting clicks from swipes.\n let pointerStartX = 0;\n let pointerStartY = 0;\n let pointerSwiped = false;\n const MOVE_THRESHOLD = 10;\n\n function handlePointerDown(event: PointerEvent): void {\n pointerStartX = event.clientX;\n pointerStartY = event.clientY;\n pointerSwiped = false;\n }\n\n function handlePointerUp(event: PointerEvent): void {\n const dx = Math.abs(event.clientX - pointerStartX);\n const dy = Math.abs(event.clientY - pointerStartY);\n pointerSwiped = dx > MOVE_THRESHOLD || dy > MOVE_THRESHOLD;\n }\n\n // ── Anchor click interception ────────────────────────────────────────────\n function handleClick(event: MouseEvent): void {\n // Ignore clicks that resulted from swipe/drag gestures.\n if (pointerSwiped) {\n pointerSwiped = false;\n return;\n }\n\n const path = event.composedPath();\n const anchor = path.find((el): el is HTMLAnchorElement => el instanceof HTMLAnchorElement);\n\n // Inside the Salla app, a link that leaves the store opens in the device's\n // browser; loaded in the app's webview it would strand the shopper there.\n if (\n anchor &&\n leavesStore(anchor, event, storeUrlRef.current) &&\n openNativeBrowser(anchor.href)\n ) {\n event.preventDefault();\n return;\n }\n\n if (!anchor || !shouldIntercept(anchor, event)) return;\n\n const samePage = isSamePage(anchor.href);\n if (tryNavigate(anchor.href, false)) {\n event.preventDefault();\n // A page load would close a web component's modal; an in-app navigation leaves it open.\n if (!samePage) closeEnclosingModal(path);\n }\n }\n\n // ── window.location.assign patch ─────────────────────────────────────────\n const origAssign = window.location.assign;\n function patchedAssign(url: string): void {\n if (!tryNavigate(url, false)) origAssign.call(window.location, url);\n }\n\n // ── window.location.replace patch ────────────────────────────────────────\n const origReplace = window.location.replace;\n function patchedReplace(url: string): void {\n if (!tryNavigate(url, true)) origReplace.call(window.location, url);\n }\n\n let assignPatched = false;\n let replacePatched = false;\n try {\n window.location.assign = patchedAssign;\n assignPatched = true;\n } catch {\n /* non-writable in this environment */\n }\n try {\n window.location.replace = patchedReplace;\n replacePatched = true;\n } catch {\n /* non-writable in this environment */\n }\n\n document.addEventListener('click', handleClick, { capture: true });\n document.addEventListener('pointerdown', handlePointerDown, { passive: true });\n document.addEventListener('pointerup', handlePointerUp, { passive: true });\n\n return () => {\n document.removeEventListener('click', handleClick, { capture: true });\n document.removeEventListener('pointerdown', handlePointerDown);\n document.removeEventListener('pointerup', handlePointerUp);\n if (assignPatched) {\n try {\n window.location.assign = origAssign;\n } catch {\n /* ignore */\n }\n }\n if (replacePatched) {\n try {\n window.location.replace = origReplace;\n } catch {\n /* ignore */\n }\n }\n };\n }, [tryNavigate]);\n}\n\n// ─── Client navigation config ─────────────────────────────────────────────────\n\nexport interface ClientNav {\n /** Framework adapter to use for client-side navigation. @default 'tanstack' */\n framework?: 'tanstack' | 'nextjs';\n /**\n * Intercept same-origin `<a>` clicks and `window.location` calls from web\n * components and route them through the framework router.\n * @default true\n */\n interceptLinks?: boolean;\n}\n\n// Framework adapter setups are registered in navigation-setups.ts to avoid circular imports.\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { configureNavigation, UnauthorizedError, NavigationProvider, resolveRelativePath } from './chunk-
|
|
1
|
+
import { configureNavigation, UnauthorizedError, NavigationProvider, resolveRelativePath } from './chunk-VEVFVWF3.js';
|
|
2
2
|
import { LinkProvider } from './chunk-BYMOPN2S.js';
|
|
3
|
-
import { useIsNativeApp } from './chunk-
|
|
4
|
-
import { onSallaEvent } from './chunk-
|
|
5
|
-
import { loginRedirectHref, resolveStoreBaseFollowsLocale, resolveStoreBase, isLoopback, hasStoreUrlBase } from './chunk-
|
|
3
|
+
import { useIsNativeApp } from './chunk-6TFM3UTF.js';
|
|
4
|
+
import { onSallaEvent } from './chunk-XMRNYUQY.js';
|
|
5
|
+
import { loginRedirectHref, resolveStoreBaseFollowsLocale, resolveStoreBase, isLoopback, hasStoreUrlBase } from './chunk-T2752RH7.js';
|
|
6
6
|
import { getTwilightContext, getRequestStore } from './chunk-6K34BCUP.js';
|
|
7
7
|
import { isLocale } from './chunk-T72DAX7R.js';
|
|
8
8
|
import { useTwilight } from './chunk-DF6FBKDN.js';
|
|
@@ -195,5 +195,5 @@ function TanStackNavigationProvider({ children }) {
|
|
|
195
195
|
}
|
|
196
196
|
|
|
197
197
|
export { NavigationSetup, TanStackLinkAdapter, TanStackNavigationProvider, createTanStackLinkAdapter, requestHostOf };
|
|
198
|
-
//# sourceMappingURL=chunk-
|
|
199
|
-
//# sourceMappingURL=chunk-
|
|
198
|
+
//# sourceMappingURL=chunk-VNHYMLGK.js.map
|
|
199
|
+
//# sourceMappingURL=chunk-VNHYMLGK.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/tanstack/link.tsx","../src/tanstack/native-app-events.tsx","../src/utils/request-host.ts","../src/tanstack/navigation.tsx"],"names":["TanStackLink","tanstackNotFound","tanstackRedirect","useParams","jsx"],"mappings":"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","file":"chunk-W5LVGFHX.js","sourcesContent":["import { forwardRef, createElement } from 'react';\nimport { Link as TanStackLink, useParams } from '@tanstack/react-router';\nimport { isLocale } from '../providers/locale-constants';\nimport type { BaseLinkProps } from '../components/common/Link.types';\n\n/**\n * Routes live under an optional `/{-$locale}` param, so a bare `to=\"/brands\"`\n * resolves with the locale omitted and the $locale loader bounces the user to\n * the fallback locale. Prefix the current locale onto internal paths that\n * don't already carry one.\n */\nexport function localizeDestination(destination: string, locale?: string) {\n if (!locale || !destination.startsWith('/') || destination.startsWith('//')) return destination;\n const firstSegment = destination.split('/')[1]?.split(/[?#]/)[0];\n if (isLocale(firstSegment)) return destination;\n return destination === '/' ? `/${locale}` : `/${locale}${destination}`;\n}\n\n/**\n * TanStack Router Link adapter.\n * Translates framework-agnostic props to TanStack Router Link props.\n */\nexport const TanStackLinkAdapter = forwardRef<HTMLAnchorElement, BaseLinkProps>(\n (\n {\n to,\n href,\n children,\n className,\n style,\n title,\n target,\n rel,\n onClick,\n preload,\n replace,\n 'aria-label': ariaLabel,\n ...rest\n },\n ref\n ) => {\n const { locale } = useParams({ strict: false }) as { locale?: string };\n const destination = localizeDestination(to ?? href ?? '/', locale);\n\n // `#` is how a block says it has nowhere to go, such as a banner with no URL. An anchor with\n // no href keeps the theme's `a` styles, and the router can neither preload nor follow it.\n if (destination === '#') {\n return createElement(\n 'a',\n { ref, className, style, title, onClick, 'aria-label': ariaLabel, ...rest },\n children\n );\n }\n\n return createElement(\n TanStackLink,\n {\n ref,\n to: destination,\n className,\n style,\n title,\n target,\n rel,\n onClick,\n preload: preload === 'intent' || preload === false ? preload : undefined,\n replace,\n 'aria-label': ariaLabel,\n ...(rest as Record<string, unknown>),\n },\n children\n );\n }\n);\n\nTanStackLinkAdapter.displayName = 'TanStackLinkAdapter';\n\n/**\n * Create a TanStack Router Link adapter component.\n */\nexport function createTanStackLinkAdapter() {\n return TanStackLinkAdapter;\n}\n","import { useEffect } from 'react';\nimport { useRouter } from '@tanstack/react-router';\nimport { resolveRelativePath } from '../providers/NavigationProvider';\nimport { useTwilight } from '../providers/twilight-context';\nimport { isLocale } from '../providers/locale-constants';\nimport { getTwilightContext } from '../twilight/context';\nimport { useIsNativeApp } from '../native-app';\nimport { onSallaEvent } from '../utils/sdk-helpers';\nimport { hasStoreUrlBase } from '../utils/store-base';\nimport { localizeDestination } from './link';\n\nconst UI_UPDATE_EVENT = 'mobile::ui.update';\nconst OPEN_ORDER_EVENT = 'mobile::open.order';\nconst NAVIGATE_TO_EVENT = 'mobile::navigate.to';\n\n/**\n * Events the native app sends into its webview. `NavigationSetup` mounts this once, so a\n * theme adds no listener of its own:\n *\n * - `mobile::ui.update` re-runs the route loaders and refetches what is on screen.\n * - `mobile::open.order` `{ id }` opens that order, with a fresh cart.\n * - `mobile::navigate.to` `{ url }` opens a notification deep link in-app. Only a link to\n * this store is followed (`deepLinkPath`), so `javascript:`, off-site and other stores'\n * URLs are dropped.\n *\n * Nothing is mounted outside the app (`useIsNativeApp()`), so a browser runs none of it.\n */\nexport function NativeAppEvents({ locale }: { locale?: string }) {\n return useIsNativeApp() ? <Listeners locale={locale} /> : null;\n}\n\nfunction Listeners({ locale }: { locale?: string }) {\n useNativeAppEvents(locale);\n return null;\n}\n\n/** The listeners themselves. `NativeAppEvents` mounts them inside the app only. */\nexport function useNativeAppEvents(locale?: string): void {\n const router = useRouter();\n const { store } = useTwilight();\n const storeUrl = store?.url;\n const username = store?.username;\n\n useEffect(() => {\n // `href`, not `to`: the router parses the query and the hash out of it.\n const open = (path: string) =>\n void router.navigate({ href: localizeDestination(path, locale) });\n\n const refresh = () => {\n void Promise.allSettled([\n router.invalidate(),\n getTwilightContext().queryClient?.refetchQueries({ type: 'active' }),\n ]);\n };\n const openOrder = (data?: unknown) => {\n const rawId = (data as { id?: unknown } | undefined)?.id;\n if (typeof rawId !== 'string' && typeof rawId !== 'number') return;\n\n const id = String(rawId).trim();\n if (!id) return;\n\n void getTwilightContext().queryClient?.invalidateQueries({ queryKey: ['cart'] });\n open(`/account/orders/${encodeURIComponent(id)}`);\n };\n const navigateTo = (data?: unknown) => {\n const url = (data as { url?: unknown } | undefined)?.url;\n if (typeof url !== 'string' || !url.trim() || !storeUrl) return;\n\n const path = deepLinkPath(url.trim(), storeUrl, username);\n if (path) void router.navigate({ href: inLocale(path, locale) });\n };\n\n const offs = [\n onSallaEvent(UI_UPDATE_EVENT, refresh),\n onSallaEvent(OPEN_ORDER_EVENT, openOrder),\n onSallaEvent(NAVIGATE_TO_EVENT, navigateTo),\n ];\n return () => offs.forEach((off) => off());\n }, [router, locale, storeUrl, username]);\n}\n\n/** A URL that names its host: `https://…` or `//…`. Anything else is a path of this app. */\nfunction isAbsoluteUrl(url: string): boolean {\n if (url.startsWith('//')) return true;\n try {\n // Without a base, only a URL with its own scheme parses.\n new URL(url);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * The application path of a deep link to this store, or null for any other link.\n *\n * It passes the test a tapped link does (`resolveRelativePath`: the store's origin, the\n * username taken off), and one more. On a shared host that origin is every store's, so\n * an absolute link has to carry this store's username: without it, another store's\n * `/ar/offers` would open this store's offers.\n */\nfunction deepLinkPath(url: string, storeUrl: string, username?: string): string | null {\n const path = resolveRelativePath(url, storeUrl, username);\n if (!path || !isAbsoluteUrl(url)) return path;\n\n // Both parse: `resolveRelativePath` returns null when either does not.\n const { pathname } = new URL(url, window.location.href);\n return hasStoreUrlBase(pathname, new URL(storeUrl).pathname, username) ? path : null;\n}\n\n/**\n * A deep link in the locale the visitor is browsing in. A notification is written in one\n * language and opened in whichever is on screen, so the link's own locale gives way.\n *\n * The prefix is written here, not by `localizeDestination`: that one leaves a path alone\n * when it already starts with a locale, and would take the slug of `/ar/en/p456` for one.\n */\nfunction inLocale(path: string, locale?: string): string {\n const first = path.split('/')[1]?.split(/[?#]/)[0];\n const own = isLocale(first) ? path.slice(first.length + 1) : path;\n const rest = own.startsWith('/') ? own : `/${own}`;\n\n if (!locale) return rest;\n return rest === '/' ? `/${locale}` : `/${locale}${rest}`;\n}\n","/**\n * What the request itself is enough to describe: its host.\n *\n * Small, and deliberately its own module rather than a helper inside the\n * middleware. This value decides two things — which store a live storefront is,\n * and whether the request is allowed to name a store at all — so it is worth\n * testing directly instead of only through the wiring that calls it.\n */\nimport { isLoopback } from './cookies';\n\n/** The part of a `Request` this needs, so a test does not have to build a whole one. */\nexport interface HostSource {\n url: string;\n headers: { get(name: string): string | null };\n}\n\n/**\n * The host this request arrived on, with its port when it has one.\n *\n * Taken from the request URL, which in a Worker is the address the platform\n * actually routed on, and from the `Host` header only when that fails.\n *\n * **`X-Forwarded-Host` is deliberately not consulted.** A client can set it, and\n * this value gates `allowsRequestStoreId` — so honouring it would be a way to\n * talk a merchant's own domain into behaving like the preview host, and from\n * there into serving a stranger's shop. The dispatcher strips that header today;\n * a theme must not be one edit to another repository's allowlist away from a\n * spoofable identity.\n */\nexport function requestHostOf(request: HostSource): string | null {\n try {\n const fromUrl = new URL(request.url).host;\n if (fromUrl) return fromUrl;\n } catch {\n /* an unparseable URL falls through to the header */\n }\n\n return request.headers.get('Host')?.trim() || null;\n}\n\n/** The origin a browser reached this host on: `http` for a dev server, `https` otherwise. */\nexport function requestOriginOf(host: string): string {\n return `${isLoopback(host.replace(/:\\d+$/, '')) ? 'http' : 'https'}://${host}`;\n}\n","import {\n useNavigate,\n useParams,\n redirect as tanstackRedirect,\n notFound as tanstackNotFound,\n} from '@tanstack/react-router';\nimport {\n NavigationProvider,\n configureNavigation,\n type NavigateOptions,\n} from '../providers/NavigationProvider';\nimport { LinkProvider } from '../providers/LinkProvider';\nimport { TanStackLinkAdapter, localizeDestination } from './link';\nimport { NativeAppEvents } from './native-app-events';\nimport { useCallback, type ReactNode } from 'react';\nimport { UnauthorizedError, type RedirectOptions } from '../providers/NavigationProvider';\nimport { getRequestStore, getTwilightContext } from '../twilight/context';\nimport { resolveStoreBase, resolveStoreBaseFollowsLocale } from '../utils/store-identity';\nimport { loginRedirectHref } from '../utils/store-base';\nimport { requestOriginOf } from '../utils/request-host';\n\nfunction currentOrigin(): string | null {\n if (typeof window !== 'undefined') return window.location.origin;\n const host = getRequestStore().requestHost;\n return host ? requestOriginOf(host) : null;\n}\n\nconfigureNavigation({\n notFound: (message?: string) => {\n throw tanstackNotFound({ data: message });\n },\n redirect: (path: string, opts?: RedirectOptions) => {\n throw tanstackRedirect({ to: path, replace: opts?.replace, statusCode: opts?.statusCode });\n },\n unauthorized: (message?: string) => {\n const origin = currentOrigin();\n const { pathname, searchStr } = getTwilightContext().location;\n const href =\n origin &&\n loginRedirectHref({\n pathname,\n searchStr,\n origin,\n base: resolveStoreBase(),\n baseFollowsLocale: resolveStoreBaseFollowsLocale(),\n });\n // A full load, because the SDK only reads `intended_to` when a page starts.\n if (href) throw tanstackRedirect({ href, reloadDocument: true, replace: true });\n throw new UnauthorizedError(message);\n },\n});\n\n/**\n * TanStack navigation setup - wraps children with NavigationProvider and LinkProvider.\n * Called by TwilightProvider when client.framework === 'tanstack'.\n */\nexport function NavigationSetup({ children }: { children: ReactNode }) {\n const navigate = useNavigate();\n const { locale } = useParams({ strict: false }) as { locale?: string };\n const navigateFn = useCallback(\n (to: string, opts?: NavigateOptions) =>\n navigate({ to: localizeDestination(to, locale), replace: opts?.replace }),\n [navigate, locale]\n );\n\n return (\n <NavigationProvider navigate={navigateFn}>\n <NativeAppEvents locale={locale} />\n <LinkProvider adapter={TanStackLinkAdapter}>{children}</LinkProvider>\n </NavigationProvider>\n );\n}\n\n/** @deprecated Use NavigationSetup instead */\nexport function TanStackNavigationProvider({ children }: { children: ReactNode }) {\n const navigate = useNavigate();\n return (\n <NavigationProvider\n navigate={(to: string, opts?: NavigateOptions) => navigate({ to, replace: opts?.replace })}\n >\n <LinkProvider adapter={TanStackLinkAdapter}>{children}</LinkProvider>\n </NavigationProvider>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/tanstack/link.tsx","../src/tanstack/native-app-events.tsx","../src/utils/request-host.ts","../src/tanstack/navigation.tsx"],"names":["TanStackLink","tanstackNotFound","tanstackRedirect","useParams","jsx"],"mappings":"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","file":"chunk-VNHYMLGK.js","sourcesContent":["import { forwardRef, createElement } from 'react';\nimport { Link as TanStackLink, useParams } from '@tanstack/react-router';\nimport { isLocale } from '../providers/locale-constants';\nimport type { BaseLinkProps } from '../components/common/Link.types';\n\n/**\n * Routes live under an optional `/{-$locale}` param, so a bare `to=\"/brands\"`\n * resolves with the locale omitted and the $locale loader bounces the user to\n * the fallback locale. Prefix the current locale onto internal paths that\n * don't already carry one.\n */\nexport function localizeDestination(destination: string, locale?: string) {\n if (!locale || !destination.startsWith('/') || destination.startsWith('//')) return destination;\n const firstSegment = destination.split('/')[1]?.split(/[?#]/)[0];\n if (isLocale(firstSegment)) return destination;\n return destination === '/' ? `/${locale}` : `/${locale}${destination}`;\n}\n\n/**\n * TanStack Router Link adapter.\n * Translates framework-agnostic props to TanStack Router Link props.\n */\nexport const TanStackLinkAdapter = forwardRef<HTMLAnchorElement, BaseLinkProps>(\n (\n {\n to,\n href,\n children,\n className,\n style,\n title,\n target,\n rel,\n onClick,\n preload,\n replace,\n 'aria-label': ariaLabel,\n ...rest\n },\n ref\n ) => {\n const { locale } = useParams({ strict: false }) as { locale?: string };\n const destination = localizeDestination(to ?? href ?? '/', locale);\n\n // `#` is how a block says it has nowhere to go, such as a banner with no URL. An anchor with\n // no href keeps the theme's `a` styles, and the router can neither preload nor follow it.\n if (destination === '#') {\n return createElement(\n 'a',\n { ref, className, style, title, onClick, 'aria-label': ariaLabel, ...rest },\n children\n );\n }\n\n return createElement(\n TanStackLink,\n {\n ref,\n to: destination,\n className,\n style,\n title,\n target,\n rel,\n onClick,\n preload: preload === 'intent' || preload === false ? preload : undefined,\n replace,\n 'aria-label': ariaLabel,\n ...(rest as Record<string, unknown>),\n },\n children\n );\n }\n);\n\nTanStackLinkAdapter.displayName = 'TanStackLinkAdapter';\n\n/**\n * Create a TanStack Router Link adapter component.\n */\nexport function createTanStackLinkAdapter() {\n return TanStackLinkAdapter;\n}\n","import { useEffect } from 'react';\nimport { useRouter } from '@tanstack/react-router';\nimport { resolveRelativePath } from '../providers/NavigationProvider';\nimport { useTwilight } from '../providers/twilight-context';\nimport { isLocale } from '../providers/locale-constants';\nimport { getTwilightContext } from '../twilight/context';\nimport { useIsNativeApp } from '../native-app';\nimport { onSallaEvent } from '../utils/sdk-helpers';\nimport { hasStoreUrlBase } from '../utils/store-base';\nimport { localizeDestination } from './link';\n\nconst UI_UPDATE_EVENT = 'mobile::ui.update';\nconst OPEN_ORDER_EVENT = 'mobile::open.order';\nconst NAVIGATE_TO_EVENT = 'mobile::navigate.to';\n\n/**\n * Events the native app sends into its webview. `NavigationSetup` mounts this once, so a\n * theme adds no listener of its own:\n *\n * - `mobile::ui.update` re-runs the route loaders and refetches what is on screen.\n * - `mobile::open.order` `{ id }` opens that order, with a fresh cart.\n * - `mobile::navigate.to` `{ url }` opens a notification deep link in-app. Only a link to\n * this store is followed (`deepLinkPath`), so `javascript:`, off-site and other stores'\n * URLs are dropped.\n *\n * Nothing is mounted outside the app (`useIsNativeApp()`), so a browser runs none of it.\n */\nexport function NativeAppEvents({ locale }: { locale?: string }) {\n return useIsNativeApp() ? <Listeners locale={locale} /> : null;\n}\n\nfunction Listeners({ locale }: { locale?: string }) {\n useNativeAppEvents(locale);\n return null;\n}\n\n/** The listeners themselves. `NativeAppEvents` mounts them inside the app only. */\nexport function useNativeAppEvents(locale?: string): void {\n const router = useRouter();\n const { store } = useTwilight();\n const storeUrl = store?.url;\n const username = store?.username;\n\n useEffect(() => {\n // `href`, not `to`: the router parses the query and the hash out of it.\n const open = (path: string) =>\n void router.navigate({ href: localizeDestination(path, locale) });\n\n const refresh = () => {\n void Promise.allSettled([\n router.invalidate(),\n getTwilightContext().queryClient?.refetchQueries({ type: 'active' }),\n ]);\n };\n const openOrder = (data?: unknown) => {\n const rawId = (data as { id?: unknown } | undefined)?.id;\n if (typeof rawId !== 'string' && typeof rawId !== 'number') return;\n\n const id = String(rawId).trim();\n if (!id) return;\n\n void getTwilightContext().queryClient?.invalidateQueries({ queryKey: ['cart'] });\n open(`/account/orders/${encodeURIComponent(id)}`);\n };\n const navigateTo = (data?: unknown) => {\n const url = (data as { url?: unknown } | undefined)?.url;\n if (typeof url !== 'string' || !url.trim() || !storeUrl) return;\n\n const path = deepLinkPath(url.trim(), storeUrl, username);\n if (path) void router.navigate({ href: inLocale(path, locale) });\n };\n\n const offs = [\n onSallaEvent(UI_UPDATE_EVENT, refresh),\n onSallaEvent(OPEN_ORDER_EVENT, openOrder),\n onSallaEvent(NAVIGATE_TO_EVENT, navigateTo),\n ];\n return () => offs.forEach((off) => off());\n }, [router, locale, storeUrl, username]);\n}\n\n/** A URL that names its host: `https://…` or `//…`. Anything else is a path of this app. */\nfunction isAbsoluteUrl(url: string): boolean {\n if (url.startsWith('//')) return true;\n try {\n // Without a base, only a URL with its own scheme parses.\n new URL(url);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * The application path of a deep link to this store, or null for any other link.\n *\n * It passes the test a tapped link does (`resolveRelativePath`: the store's origin, the\n * username taken off), and one more. On a shared host that origin is every store's, so\n * an absolute link has to carry this store's username: without it, another store's\n * `/ar/offers` would open this store's offers.\n */\nfunction deepLinkPath(url: string, storeUrl: string, username?: string): string | null {\n const path = resolveRelativePath(url, storeUrl, username);\n if (!path || !isAbsoluteUrl(url)) return path;\n\n // Both parse: `resolveRelativePath` returns null when either does not.\n const { pathname } = new URL(url, window.location.href);\n return hasStoreUrlBase(pathname, new URL(storeUrl).pathname, username) ? path : null;\n}\n\n/**\n * A deep link in the locale the visitor is browsing in. A notification is written in one\n * language and opened in whichever is on screen, so the link's own locale gives way.\n *\n * The prefix is written here, not by `localizeDestination`: that one leaves a path alone\n * when it already starts with a locale, and would take the slug of `/ar/en/p456` for one.\n */\nfunction inLocale(path: string, locale?: string): string {\n const first = path.split('/')[1]?.split(/[?#]/)[0];\n const own = isLocale(first) ? path.slice(first.length + 1) : path;\n const rest = own.startsWith('/') ? own : `/${own}`;\n\n if (!locale) return rest;\n return rest === '/' ? `/${locale}` : `/${locale}${rest}`;\n}\n","/**\n * What the request itself is enough to describe: its host.\n *\n * Small, and deliberately its own module rather than a helper inside the\n * middleware. This value decides two things — which store a live storefront is,\n * and whether the request is allowed to name a store at all — so it is worth\n * testing directly instead of only through the wiring that calls it.\n */\nimport { isLoopback } from './cookies';\n\n/** The part of a `Request` this needs, so a test does not have to build a whole one. */\nexport interface HostSource {\n url: string;\n headers: { get(name: string): string | null };\n}\n\n/**\n * The host this request arrived on, with its port when it has one.\n *\n * Taken from the request URL, which in a Worker is the address the platform\n * actually routed on, and from the `Host` header only when that fails.\n *\n * **`X-Forwarded-Host` is deliberately not consulted.** A client can set it, and\n * this value gates `allowsRequestStoreId` — so honouring it would be a way to\n * talk a merchant's own domain into behaving like the preview host, and from\n * there into serving a stranger's shop. The dispatcher strips that header today;\n * a theme must not be one edit to another repository's allowlist away from a\n * spoofable identity.\n */\nexport function requestHostOf(request: HostSource): string | null {\n try {\n const fromUrl = new URL(request.url).host;\n if (fromUrl) return fromUrl;\n } catch {\n /* an unparseable URL falls through to the header */\n }\n\n return request.headers.get('Host')?.trim() || null;\n}\n\n/** The origin a browser reached this host on: `http` for a dev server, `https` otherwise. */\nexport function requestOriginOf(host: string): string {\n return `${isLoopback(host.replace(/:\\d+$/, '')) ? 'http' : 'https'}://${host}`;\n}\n","import {\n useNavigate,\n useParams,\n redirect as tanstackRedirect,\n notFound as tanstackNotFound,\n} from '@tanstack/react-router';\nimport {\n NavigationProvider,\n configureNavigation,\n type NavigateOptions,\n} from '../providers/NavigationProvider';\nimport { LinkProvider } from '../providers/LinkProvider';\nimport { TanStackLinkAdapter, localizeDestination } from './link';\nimport { NativeAppEvents } from './native-app-events';\nimport { useCallback, type ReactNode } from 'react';\nimport { UnauthorizedError, type RedirectOptions } from '../providers/NavigationProvider';\nimport { getRequestStore, getTwilightContext } from '../twilight/context';\nimport { resolveStoreBase, resolveStoreBaseFollowsLocale } from '../utils/store-identity';\nimport { loginRedirectHref } from '../utils/store-base';\nimport { requestOriginOf } from '../utils/request-host';\n\nfunction currentOrigin(): string | null {\n if (typeof window !== 'undefined') return window.location.origin;\n const host = getRequestStore().requestHost;\n return host ? requestOriginOf(host) : null;\n}\n\nconfigureNavigation({\n notFound: (message?: string) => {\n throw tanstackNotFound({ data: message });\n },\n redirect: (path: string, opts?: RedirectOptions) => {\n throw tanstackRedirect({ to: path, replace: opts?.replace, statusCode: opts?.statusCode });\n },\n unauthorized: (message?: string) => {\n const origin = currentOrigin();\n const { pathname, searchStr } = getTwilightContext().location;\n const href =\n origin &&\n loginRedirectHref({\n pathname,\n searchStr,\n origin,\n base: resolveStoreBase(),\n baseFollowsLocale: resolveStoreBaseFollowsLocale(),\n });\n // A full load, because the SDK only reads `intended_to` when a page starts.\n if (href) throw tanstackRedirect({ href, reloadDocument: true, replace: true });\n throw new UnauthorizedError(message);\n },\n});\n\n/**\n * TanStack navigation setup - wraps children with NavigationProvider and LinkProvider.\n * Called by TwilightProvider when client.framework === 'tanstack'.\n */\nexport function NavigationSetup({ children }: { children: ReactNode }) {\n const navigate = useNavigate();\n const { locale } = useParams({ strict: false }) as { locale?: string };\n const navigateFn = useCallback(\n (to: string, opts?: NavigateOptions) =>\n navigate({ to: localizeDestination(to, locale), replace: opts?.replace }),\n [navigate, locale]\n );\n\n return (\n <NavigationProvider navigate={navigateFn}>\n <NativeAppEvents locale={locale} />\n <LinkProvider adapter={TanStackLinkAdapter}>{children}</LinkProvider>\n </NavigationProvider>\n );\n}\n\n/** @deprecated Use NavigationSetup instead */\nexport function TanStackNavigationProvider({ children }: { children: ReactNode }) {\n const navigate = useNavigate();\n return (\n <NavigationProvider\n navigate={(to: string, opts?: NavigateOptions) => navigate({ to, replace: opts?.replace })}\n >\n <LinkProvider adapter={TanStackLinkAdapter}>{children}</LinkProvider>\n </NavigationProvider>\n );\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { rememberProductPreview } from './chunk-
|
|
2
|
-
import { getActiveScope, api } from './chunk-
|
|
1
|
+
import { rememberProductPreview } from './chunk-7PPNAVBF.js';
|
|
2
|
+
import { getActiveScope, api } from './chunk-2DUN6DZK.js';
|
|
3
3
|
import { queryOptions } from '@tanstack/react-query';
|
|
4
4
|
|
|
5
5
|
var wishlist = {
|
|
@@ -31,5 +31,5 @@ var wishlist = {
|
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
export { wishlist };
|
|
34
|
-
//# sourceMappingURL=chunk-
|
|
35
|
-
//# sourceMappingURL=chunk-
|
|
34
|
+
//# sourceMappingURL=chunk-VQO4TTPE.js.map
|
|
35
|
+
//# sourceMappingURL=chunk-VQO4TTPE.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api/wishlist.ts"],"names":[],"mappings":";;;;AAmBO,IAAM,QAAA,GAAW;AAAA,EACtB,IAAA,EAAM,OAAO,MAAA,GAA6B,EAAC,KAAmC;AAC5E,IAAA,MAAM,EAAE,IAAA,GAAO,CAAA,EAAG,UAAU,EAAA,EAAI,UAAA,EAAY,QAAO,GAAI,MAAA;AAEvD,IAAA,MAAM,YAAA,GAAe,IAAI,eAAA,EAAgB;AACzC,IAAA,YAAA,CAAa,GAAA,CAAI,UAAU,UAAU,CAAA;AACrC,IAAA,YAAA,CAAa,GAAA,CAAI,MAAA,EAAQ,MAAA,CAAO,IAAI,CAAC,CAAA;AACrC,IAAA,YAAA,CAAa,GAAA,CAAI,UAAA,EAAY,MAAA,CAAO,OAAO,CAAC,CAAA;AAE5C,IAAA,IAAI,eAAe,MAAA,EAAW;AAC5B,MAAA,YAAA,CAAa,GAAA,CAAI,YAAA,EAAc,UAAA,GAAa,GAAA,GAAM,GAAG,CAAA;AAAA,IACvD;AAEA,IAAA,MAAM,UAAmC,EAAC;AAC1C,IAAA,IAAI,MAAA,UAAgB,MAAA,GAAS,MAAA;AAE7B,IAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CACpB,GAAA,CAAI,CAAA,SAAA,EAAY,YAAA,CAAa,QAAA,EAAU,CAAA,CAAA,EAAI,OAAc,CAAA,CACzD,IAAA,EAA2B;AAE9B,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,IAAA,IAAQ,EAAC;AAChC,IAAA,KAAA,MAAW,IAAA,IAAQ,KAAA,EAAO,sBAAA,CAAuB,IAAI,CAAA;AAErD,IAAA,OAAO;AAAA,MACL,KAAA;AAAA,MACA,IAAA,EAAM,QAAA,CAAS,MAAA,EAAQ,IAAA,IAAQ;AAAA,KACjC;AAAA,EACF,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,IAAA,EAAM,CAAC,MAAA,KACL,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,UAAA,EAAY,MAAA,EAAQ,QAAQ,EAAE,KAAA,EAAO,cAAA,EAAe,EAAG,CAAA;AAAA,MAClE,OAAA,EAAS,CAAC,EAAE,MAAA,EAAO,KAAM,QAAA,CAAS,IAAA,CAAK,EAAE,GAAG,MAAA,EAAQ,MAAA,EAAQ;AAAA,KAC7D;AAAA;AAEP","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/api/wishlist.ts"],"names":[],"mappings":";;;;AAmBO,IAAM,QAAA,GAAW;AAAA,EACtB,IAAA,EAAM,OAAO,MAAA,GAA6B,EAAC,KAAmC;AAC5E,IAAA,MAAM,EAAE,IAAA,GAAO,CAAA,EAAG,UAAU,EAAA,EAAI,UAAA,EAAY,QAAO,GAAI,MAAA;AAEvD,IAAA,MAAM,YAAA,GAAe,IAAI,eAAA,EAAgB;AACzC,IAAA,YAAA,CAAa,GAAA,CAAI,UAAU,UAAU,CAAA;AACrC,IAAA,YAAA,CAAa,GAAA,CAAI,MAAA,EAAQ,MAAA,CAAO,IAAI,CAAC,CAAA;AACrC,IAAA,YAAA,CAAa,GAAA,CAAI,UAAA,EAAY,MAAA,CAAO,OAAO,CAAC,CAAA;AAE5C,IAAA,IAAI,eAAe,MAAA,EAAW;AAC5B,MAAA,YAAA,CAAa,GAAA,CAAI,YAAA,EAAc,UAAA,GAAa,GAAA,GAAM,GAAG,CAAA;AAAA,IACvD;AAEA,IAAA,MAAM,UAAmC,EAAC;AAC1C,IAAA,IAAI,MAAA,UAAgB,MAAA,GAAS,MAAA;AAE7B,IAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CACpB,GAAA,CAAI,CAAA,SAAA,EAAY,YAAA,CAAa,QAAA,EAAU,CAAA,CAAA,EAAI,OAAc,CAAA,CACzD,IAAA,EAA2B;AAE9B,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,IAAA,IAAQ,EAAC;AAChC,IAAA,KAAA,MAAW,IAAA,IAAQ,KAAA,EAAO,sBAAA,CAAuB,IAAI,CAAA;AAErD,IAAA,OAAO;AAAA,MACL,KAAA;AAAA,MACA,IAAA,EAAM,QAAA,CAAS,MAAA,EAAQ,IAAA,IAAQ;AAAA,KACjC;AAAA,EACF,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,IAAA,EAAM,CAAC,MAAA,KACL,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,UAAA,EAAY,MAAA,EAAQ,QAAQ,EAAE,KAAA,EAAO,cAAA,EAAe,EAAG,CAAA;AAAA,MAClE,OAAA,EAAS,CAAC,EAAE,MAAA,EAAO,KAAM,QAAA,CAAS,IAAA,CAAK,EAAE,GAAG,MAAA,EAAQ,MAAA,EAAQ;AAAA,KAC7D;AAAA;AAEP","file":"chunk-VQO4TTPE.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api, getActiveScope } from './client';\nimport {\n rememberProductPreview,\n type ProductsListResult,\n type ProductsListResponse,\n} from './product';\n\nexport interface WishlistListParams {\n page?: number;\n perPage?: number;\n filterable?: boolean;\n signal?: AbortSignal;\n}\n\n/**\n * Wishlist API — page-based pagination only.\n * Kept separate from product.list to avoid mixing cursor and page pagination strategies.\n */\nexport const wishlist = {\n list: async (params: WishlistListParams = {}): Promise<ProductsListResult> => {\n const { page = 1, perPage = 15, filterable, signal } = params;\n\n const searchParams = new URLSearchParams();\n searchParams.set('source', 'wishlist');\n searchParams.set('page', String(page));\n searchParams.set('per_page', String(perPage));\n\n if (filterable !== undefined) {\n searchParams.set('filterable', filterable ? '1' : '0');\n }\n\n const options: Record<string, unknown> = {};\n if (signal) options.signal = signal;\n\n const response = await api\n .get(`products?${searchParams.toString()}`, options as any)\n .json<ProductsListResponse>();\n\n const items = response.data ?? [];\n for (const item of items) rememberProductPreview(item);\n\n return {\n items,\n next: response.cursor?.next ?? null,\n };\n },\n\n queries: {\n list: (params: Omit<WishlistListParams, 'signal'>) =>\n queryOptions({\n queryKey: ['wishlist', 'list', params, { scope: getActiveScope() }],\n queryFn: ({ signal }) => wishlist.list({ ...params, signal }),\n }),\n },\n};\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { api } from './chunk-
|
|
1
|
+
import { api } from './chunk-2DUN6DZK.js';
|
|
2
2
|
|
|
3
3
|
// src/api/wallet.ts
|
|
4
4
|
var wallet = {
|
|
@@ -20,5 +20,5 @@ var wallet = {
|
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
export { wallet };
|
|
23
|
-
//# sourceMappingURL=chunk-
|
|
24
|
-
//# sourceMappingURL=chunk-
|
|
23
|
+
//# sourceMappingURL=chunk-X6WDFQYL.js.map
|
|
24
|
+
//# sourceMappingURL=chunk-X6WDFQYL.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api/wallet.ts"],"names":[],"mappings":";;;AAgCO,IAAM,MAAA,GAAS;AAAA,EACpB,IAAA,EAAM,OAAO,MAAA,GAA2B,EAAC,KAAiC;AACxE,IAAA,MAAM,EAAE,IAAA,GAAO,CAAA,EAAG,OAAA,GAAU,EAAA,EAAI,QAAO,GAAI,MAAA;AAE3C,IAAA,MAAM,YAAA,GAAe,IAAI,eAAA,EAAgB;AACzC,IAAA,YAAA,CAAa,GAAA,CAAI,MAAA,EAAQ,MAAA,CAAO,IAAI,CAAC,CAAA;AACrC,IAAA,YAAA,CAAa,GAAA,CAAI,UAAA,EAAY,MAAA,CAAO,OAAO,CAAC,CAAA;AAE5C,IAAA,MAAM,UAAmC,EAAC;AAC1C,IAAA,IAAI,MAAA,UAAgB,MAAA,GAAS,MAAA;AAE7B,IAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CACpB,GAAA,CAAI,CAAA,eAAA,EAAkB,YAAA,CAAa,QAAA,EAAU,CAAA,CAAA,EAAI,OAAc,CAAA,CAC/D,IAAA,EAAsE;AAEzE,IAAA,MAAM,YAAA,GAAe,SAAS,IAAA,CAAK,YAAA;AAEnC,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,YAAA,CAAa,IAAA,IAAQ,EAAC;AAAA,MAC7B,MAAM,YAAA,CAAa,aAAA;AAAA,MACnB,OAAA,EAAS,SAAS,IAAA,CAAK;AAAA,KACzB;AAAA,EACF;AACF","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/api/wallet.ts"],"names":[],"mappings":";;;AAgCO,IAAM,MAAA,GAAS;AAAA,EACpB,IAAA,EAAM,OAAO,MAAA,GAA2B,EAAC,KAAiC;AACxE,IAAA,MAAM,EAAE,IAAA,GAAO,CAAA,EAAG,OAAA,GAAU,EAAA,EAAI,QAAO,GAAI,MAAA;AAE3C,IAAA,MAAM,YAAA,GAAe,IAAI,eAAA,EAAgB;AACzC,IAAA,YAAA,CAAa,GAAA,CAAI,MAAA,EAAQ,MAAA,CAAO,IAAI,CAAC,CAAA;AACrC,IAAA,YAAA,CAAa,GAAA,CAAI,UAAA,EAAY,MAAA,CAAO,OAAO,CAAC,CAAA;AAE5C,IAAA,MAAM,UAAmC,EAAC;AAC1C,IAAA,IAAI,MAAA,UAAgB,MAAA,GAAS,MAAA;AAE7B,IAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CACpB,GAAA,CAAI,CAAA,eAAA,EAAkB,YAAA,CAAa,QAAA,EAAU,CAAA,CAAA,EAAI,OAAc,CAAA,CAC/D,IAAA,EAAsE;AAEzE,IAAA,MAAM,YAAA,GAAe,SAAS,IAAA,CAAK,YAAA;AAEnC,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,YAAA,CAAa,IAAA,IAAQ,EAAC;AAAA,MAC7B,MAAM,YAAA,CAAa,aAAA;AAAA,MACnB,OAAA,EAAS,SAAS,IAAA,CAAK;AAAA,KACzB;AAAA,EACF;AACF","file":"chunk-X6WDFQYL.js","sourcesContent":["import { api } from './client';\n\nexport interface TransactionItem {\n id: number;\n order_id: number;\n transaction_type: string;\n action_type: string;\n type: string;\n title: string;\n description: string;\n amount: number;\n created_at: number;\n expired_at: number;\n}\n\nexport interface WalletListParams {\n page?: number;\n perPage?: number;\n signal?: AbortSignal;\n}\n\nexport interface WalletListResponse {\n data: TransactionItem[];\n next_page_url: string | null;\n}\n\nexport interface WalletListResult {\n items: TransactionItem[];\n next: string | null;\n balance: number;\n}\n\nexport const wallet = {\n list: async (params: WalletListParams = {}): Promise<WalletListResult> => {\n const { page = 1, perPage = 10, signal } = params;\n\n const searchParams = new URLSearchParams();\n searchParams.set('page', String(page));\n searchParams.set('per_page', String(perPage));\n\n const options: Record<string, unknown> = {};\n if (signal) options.signal = signal;\n\n const response = await api\n .get(`balance/wallet?${searchParams.toString()}`, options as any)\n .json<{ data: { transactions: WalletListResponse; balance: number } }>();\n\n const transactions = response.data.transactions;\n\n return {\n items: transactions.data ?? [],\n next: transactions.next_page_url,\n balance: response.data.balance,\n };\n },\n};\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getInjectedRuntimeEnv, resolveStoreIdentifier } from './chunk-
|
|
1
|
+
import { getInjectedRuntimeEnv, resolveStoreIdentifier } from './chunk-T2752RH7.js';
|
|
2
2
|
import { getRequestStore, getTwilightContext } from './chunk-6K34BCUP.js';
|
|
3
3
|
|
|
4
4
|
// src/utils/theme-version.ts
|
|
@@ -121,5 +121,5 @@ function syncSdkThemeVersion(headers) {
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
export { getSallaSDK, getStoreIdentifier, onSallaEvent, requestedThemeVersionId, resolveThemeVersionId, syncSdkLocale, syncSdkThemeVersion, whenSallaLoaded, whenSallaReady, withSdkThemeVersion };
|
|
124
|
-
//# sourceMappingURL=chunk-
|
|
125
|
-
//# sourceMappingURL=chunk-
|
|
124
|
+
//# sourceMappingURL=chunk-XMRNYUQY.js.map
|
|
125
|
+
//# sourceMappingURL=chunk-XMRNYUQY.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/theme-version.ts","../src/utils/sdk-helpers.ts"],"names":[],"mappings":"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","file":"chunk-NHA4SBKG.js","sourcesContent":["/**\n * @fileoverview Which version of the theme's settings to render — the one answer,\n * in one place.\n *\n * A merchant's theme settings are versioned. An ordinary storefront visit names\n * no version and gets the live one; the API decides, and reports it back as\n * `theme.profile.id`. Two surfaces need a different one, and both address it in\n * the URL of an iframe:\n *\n * - the merchant's theme editor at `s.salla.sa/themes/editor/…`, which shows a\n * draft version beside the controls that are editing it;\n * - a partner running the theme locally, whose dev server is the iframe.\n *\n * Written as a module of its own rather than inline at the one call site,\n * because `store-identity.ts` exists for exactly this reason: the identifier a\n * request resolved and the identifier it sent were two different values for\n * days, in two files, and every test passed. A second implementation of this is\n * the bug, not a refactor away from one.\n */\nimport { getRequestStore, getTwilightContext } from '../twilight/context';\nimport type { StoreContext } from '../api/store';\nimport { getInjectedRuntimeEnv } from './runtime-env';\n\n/**\n * The version this request asked for, or null when it asked for none.\n *\n * Deliberately excludes the version the *settings* name. This is the answer to\n * \"what did the caller address?\", and it has to be available before any settings\n * exist — React Query keys are built from it, and a key that means one thing\n * during SSR and another after hydration is how a page refetches everything it\n * was just handed.\n *\n * 1. what the request named, seeded by `twilightMiddleware` on a host permitted\n * to name one;\n * 2. what SSR resolved and published into the head, which is all the browser has\n * once the dispatcher has stripped `?versionId=` from the URL.\n */\nexport function requestedThemeVersionId(): string | null {\n const { versionId } = getRequestStore();\n if (versionId) return versionId;\n\n return getInjectedRuntimeEnv().versionId || null;\n}\n\n/**\n * The version every Salla API call is answered with — what goes in `s-version-id`.\n *\n * The requested version outranks the settings, because a request that named one\n * is the only reason this is ever anything but the live version: falling back to\n * the settings there would let the first answer overwrite the question.\n *\n * The settings' own `theme.profile.id` stays as the fallback, unchanged. It is\n * what this header has always carried, and on an ordinary storefront it still\n * is — it keeps the rest of a page's calls pinned to the version the settings\n * call resolved, rather than letting a version go live mid-render.\n *\n * That pin is only good for the scope the settings were requested with. Each\n * market (scope) has its own version, and the API lets a named version outrank\n * the market's: once the shopper switches market, the loaded settings still\n * describe the previous one, and replaying their version — on the settings call\n * for the new market first of all — gets the previous market's theme back, for\n * good. So the version is replayed only while the active scope is the one the\n * settings were answered for (`store.scope`), which is not always the one they\n * were requested for (`requestedScopeId`): the API falls back to another scope\n * when it does not accept the requested one, and that scope's version must not\n * ride along on the next request for the requested one. With no active scope it\n * is replayed only for settings requested without one. Otherwise nothing is\n * sent and the API picks the version of the scope on the request.\n *\n * `activeScopeId` is passed in by the caller that already resolved the scope for\n * its `s-scope-*` headers.\n *\n * Reading the settings is guarded because `getTwilightContext().settings` throws\n * a `SettingsError` when they have not loaded — which is the normal state on the\n * very first call, the settings call itself.\n */\n/** Whether `settings` were answered for `activeScopeId` (see {@link resolveThemeVersionId}). */\nfunction answersScope(settings: StoreContext | null | undefined, activeScopeId: string | null) {\n const requestedScopeId = settings?.requestedScopeId ?? null;\n if (activeScopeId == null) return requestedScopeId == null;\n const answeredScopeId = settings?.store?.scope?.id;\n return (answeredScopeId != null ? String(answeredScopeId) : requestedScopeId) === activeScopeId;\n}\n\nexport function resolveThemeVersionId(activeScopeId: string | null = null): string | null {\n const requested = requestedThemeVersionId();\n if (requested) return requested;\n\n try {\n const settings = getTwilightContext().settings;\n if (!answersScope(settings, activeScopeId)) return null;\n\n const profileId = settings?.theme?.profile?.id;\n return profileId != null ? String(profileId) : null;\n } catch {\n return null;\n }\n}\n","export type { StoreContext } from '../api/store';\nimport type { StoreContext } from '../api/store';\nimport type { SallaSDK } from '../types/salla-sdk';\nimport { resolveStoreIdentifier } from './store-identity';\nimport { requestedThemeVersionId } from './theme-version';\n\nconst isBrowser = typeof window !== 'undefined';\n\n/**\n * Which store to ask the API about — see {@link resolveStoreIdentifier}.\n *\n * A delegation, not a second implementation. This name is the one on the wire\n * (`api/client.ts` sets the `store-identifier` header from it) and the one\n * themes import from `@salla.sa/twilight-theme-engine/utils`, so it stays; what\n * it must never do again is answer differently from the resolver everything\n * else asks. It had its own copy of the order once, missing the store the\n * request names and preferring the build-time `VITE_STORE_DOMAIN` that a\n * deployed worker does not have — so every published theme sent an empty\n * identifier and rendered \"Store Unavailable\".\n */\nexport function getStoreIdentifier(explicit?: string): string {\n return resolveStoreIdentifier(explicit);\n}\n\n/**\n * Get Salla SDK instance if available\n */\nexport function getSallaSDK(): typeof window.salla | undefined {\n if (!isBrowser) return undefined;\n return window.salla;\n}\n\n/** Dispatched on `window` by the SDK as the last step of loading (twilight `src/index.js`). */\nconst SDK_CREATED_EVENT = 'salla::created';\n\nconst noop = () => {};\n\n/**\n * Whether `window.salla` is the SDK, rather than the stub that stands in for it.\n *\n * ⚠️ `window.salla` exists from the first bytes of the page. The `twilight-init`\n * head script defines it with an `onReady`, so app snippets can queue work, and\n * the SDK — a deferred module — fills it in later. React can hydrate and run\n * effects in between, and there `window.salla?.event.on(…)` passes its `?.` and\n * throws `Cannot read properties of undefined (reading 'on')`.\n *\n * The SDK defines `init` and `event` in one synchronous module evaluation and the\n * stub has neither, so either one means it has loaded.\n */\nfunction isLoaded(sdk: typeof window.salla): sdk is SallaSDK {\n return typeof sdk?.init === 'function' || typeof sdk?.event?.on === 'function';\n}\n\n/** An SDK whose event bus can take a listener — what {@link onSallaEvent} needs. */\nfunction hasEventBus(sdk: typeof window.salla): sdk is SallaSDK {\n return typeof sdk?.event?.on === 'function';\n}\n\n/**\n * Run `callback` with the SDK as soon as it has loaded: now if it has, otherwise\n * when it announces itself.\n *\n * Returns a cancel for an effect's cleanup, so a component that unmounts first\n * never has the callback run. An effect that returned early when the SDK was not\n * there yet never ran again — on a cold load, where hydration beats the SDK, the\n * engine never initialised it at all.\n */\nexport function whenSallaLoaded(callback: (sdk: SallaSDK) => void): () => void {\n return whenSalla(isLoaded, callback);\n}\n\nfunction whenSalla(\n isUsable: (sdk: typeof window.salla) => sdk is SallaSDK,\n callback: (sdk: SallaSDK) => void\n): () => void {\n if (!isBrowser) return noop;\n\n if (isUsable(window.salla)) {\n callback(window.salla);\n return noop;\n }\n\n let settled = false;\n const onCreated = () => {\n const sdk = window.salla;\n if (settled || !isUsable(sdk)) return;\n settled = true;\n window.removeEventListener(SDK_CREATED_EVENT, onCreated);\n callback(sdk);\n };\n window.addEventListener(SDK_CREATED_EVENT, onCreated);\n\n return () => {\n settled = true;\n window.removeEventListener(SDK_CREATED_EVENT, onCreated);\n };\n}\n\n/**\n * Run `callback` once the SDK has loaded **and been initialised** — for work that\n * talks to the API, which needs the store config `init` sets.\n *\n * Loaded is not enough for that: `init` finishes asynchronously, so a cart lookup\n * made the moment the SDK announces itself goes out without a store identifier\n * and is answered `Store Identifier not found`. Returns a cancel, as\n * {@link whenSallaLoaded} does.\n *\n * A rejected `onReady` still runs `callback`, as `useTwilightInit` carries on past\n * one: it means a partial initialisation, and waiting on it would leave the caller\n * waiting for good.\n */\nexport function whenSallaReady(callback: (sdk: SallaSDK) => void): () => void {\n let cancelled = false;\n const cancel = whenSallaLoaded((sdk) => {\n void new Promise((resolve) => resolve(sdk.onReady?.())).catch(noop).then(() => {\n if (!cancelled) callback(sdk);\n });\n });\n return () => {\n cancelled = true;\n cancel();\n };\n}\n\n/**\n * `salla.event.on(name, listener)` once the SDK has loaded. Returns the matching\n * unsubscribe, which also cancels a subscription still waiting for the SDK.\n *\n * Removed from the emitter it was added to, not from whatever `window.salla` is\n * by the time the component unmounts.\n *\n * Waits for an event bus specifically, not for \"loaded\": an SDK is recognised by\n * `init` alone, and subscribing on one without a bus would throw.\n */\nexport function onSallaEvent(name: string, listener: (...args: unknown[]) => void): () => void {\n let bus: SallaSDK['event'] | undefined;\n const cancel = whenSalla(hasEventBus, (sdk) => {\n bus = sdk.event;\n bus.on(name, listener);\n });\n return () => {\n cancel();\n bus?.off?.(name, listener);\n };\n}\n\n/**\n * Push the active route locale onto the Salla SDK.\n *\n * Why this is needed (and why it must run on every navigation):\n * - The SDK seeds its locale from `navigator.language` — the theme sets no `s-lang`\n * cookie or `window.locale` — so an English browser starts the SDK in `en` even on\n * an `/ar` store.\n * - The SDK fixes its axios `accept-language` header ONCE, at init. `salla.lang.setLocale`\n * only swaps UI translations (it never touches the header), and `salla.init()` is a\n * no-op after `Salla.status === 'ready'`, so the header never refreshes on its own.\n * - `profile::info.fetched` (login / profile refresh on navigation) overrides the header\n * to the *account's* language.\n *\n * Net result without this: `salla.api.*` calls (cart/product details) return data in the\n * wrong locale — e.g. English cart item names on `/ar/cart` — intermittently, depending on\n * load order and whether a profile fetch ran. Re-asserting the URL locale here keeps the\n * header correct. No-op on the server and until the SDK exposes the methods.\n */\nexport function syncSdkLocale(locale: string): void {\n const sdk = getSallaSDK();\n if (!sdk || !locale) return;\n try {\n sdk.lang?.setLocale?.(locale);\n sdk.api?.setHeader?.('accept-language', locale);\n // The localization modal swaps `/${user.language_code}/` in the URL on submit;\n // the SDK never sets this locally, so without it the switch reloads the same page.\n sdk.config?.set?.('user.language_code', locale);\n } catch {\n // SDK partially loaded — the header is re-asserted on the next navigation.\n }\n}\n\n/**\n * The `s-version-id` the SDK sends: the version the request named, else the one\n * the settings report.\n *\n * The request outranks the settings here for the reason it does in\n * `resolveThemeVersionId`. `headers['s-version-id']` is the version the API\n * *answered with*, and for a version it cannot reach it reports the live one\n * while rendering defaults. Read alone, a preview's `salla.api.*` calls asked\n * about the live version while the engine's own asked about the previewed one,\n * so one page showed two versions.\n */\nfunction sdkThemeVersionId(headers: StoreContext['headers']): string | null {\n const versionId = requestedThemeVersionId() ?? headers?.['s-version-id'];\n return versionId != null ? String(versionId) : null;\n}\n\n/**\n * Settings as the SDK's `init` should copy them: with `headers` naming the\n * version {@link sdkThemeVersionId} picks.\n *\n * `init` spreads `headers` over its axios defaults, and on a first load nothing\n * re-asserts the version afterwards: TanStack restores the root match's context\n * instead of re-running `rootBeforeLoad` in the browser, so\n * {@link syncSdkThemeVersion} first runs on a client navigation.\n */\nexport function withSdkThemeVersion<T extends Pick<StoreContext, 'headers'>>(settings: T): T {\n const versionId = requestedThemeVersionId();\n if (!versionId) return settings;\n return { ...settings, headers: { ...settings.headers, 's-version-id': versionId } };\n}\n\n/**\n * Push the theme version onto the Salla SDK: the requested one, else the one the\n * current settings name (see {@link sdkThemeVersionId}).\n *\n * The SDK copies `settings.headers` into its axios defaults ONCE, at init, and\n * `s-version-id` is one of them. Settings refetched on the client — the shopper\n * switched market, and each market has its own version — name a different one,\n * and without this every `salla.api.*` call keeps asking for the previous\n * market's version until a full page load. Settings that name no version take\n * the header off instead, so the SDK asks for the live one like the engine's own\n * client does. No-op on the server and until the SDK exposes its api.\n */\nexport function syncSdkThemeVersion(headers: StoreContext['headers']): void {\n const sdk = getSallaSDK();\n if (!sdk) return;\n const versionId = sdkThemeVersionId(headers);\n try {\n if (versionId != null) sdk.api?.setHeader?.('s-version-id', versionId);\n else delete sdk.api?.axios?.defaults?.headers?.common?.['s-version-id'];\n } catch {\n // SDK partially loaded — the header is re-asserted on the next navigation.\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/theme-version.ts","../src/utils/sdk-helpers.ts"],"names":[],"mappings":"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","file":"chunk-XMRNYUQY.js","sourcesContent":["/**\n * @fileoverview Which version of the theme's settings to render — the one answer,\n * in one place.\n *\n * A merchant's theme settings are versioned. An ordinary storefront visit names\n * no version and gets the live one; the API decides, and reports it back as\n * `theme.profile.id`. Two surfaces need a different one, and both address it in\n * the URL of an iframe:\n *\n * - the merchant's theme editor at `s.salla.sa/themes/editor/…`, which shows a\n * draft version beside the controls that are editing it;\n * - a partner running the theme locally, whose dev server is the iframe.\n *\n * Written as a module of its own rather than inline at the one call site,\n * because `store-identity.ts` exists for exactly this reason: the identifier a\n * request resolved and the identifier it sent were two different values for\n * days, in two files, and every test passed. A second implementation of this is\n * the bug, not a refactor away from one.\n */\nimport { getRequestStore, getTwilightContext } from '../twilight/context';\nimport type { StoreContext } from '../api/store';\nimport { getInjectedRuntimeEnv } from './runtime-env';\n\n/**\n * The version this request asked for, or null when it asked for none.\n *\n * Deliberately excludes the version the *settings* name. This is the answer to\n * \"what did the caller address?\", and it has to be available before any settings\n * exist — React Query keys are built from it, and a key that means one thing\n * during SSR and another after hydration is how a page refetches everything it\n * was just handed.\n *\n * 1. what the request named, seeded by `twilightMiddleware` on a host permitted\n * to name one;\n * 2. what SSR resolved and published into the head, which is all the browser has\n * once the dispatcher has stripped `?versionId=` from the URL.\n */\nexport function requestedThemeVersionId(): string | null {\n const { versionId } = getRequestStore();\n if (versionId) return versionId;\n\n return getInjectedRuntimeEnv().versionId || null;\n}\n\n/**\n * The version every Salla API call is answered with — what goes in `s-version-id`.\n *\n * The requested version outranks the settings, because a request that named one\n * is the only reason this is ever anything but the live version: falling back to\n * the settings there would let the first answer overwrite the question.\n *\n * The settings' own `theme.profile.id` stays as the fallback, unchanged. It is\n * what this header has always carried, and on an ordinary storefront it still\n * is — it keeps the rest of a page's calls pinned to the version the settings\n * call resolved, rather than letting a version go live mid-render.\n *\n * That pin is only good for the scope the settings were requested with. Each\n * market (scope) has its own version, and the API lets a named version outrank\n * the market's: once the shopper switches market, the loaded settings still\n * describe the previous one, and replaying their version — on the settings call\n * for the new market first of all — gets the previous market's theme back, for\n * good. So the version is replayed only while the active scope is the one the\n * settings were answered for (`store.scope`), which is not always the one they\n * were requested for (`requestedScopeId`): the API falls back to another scope\n * when it does not accept the requested one, and that scope's version must not\n * ride along on the next request for the requested one. With no active scope it\n * is replayed only for settings requested without one. Otherwise nothing is\n * sent and the API picks the version of the scope on the request.\n *\n * `activeScopeId` is passed in by the caller that already resolved the scope for\n * its `s-scope-*` headers.\n *\n * Reading the settings is guarded because `getTwilightContext().settings` throws\n * a `SettingsError` when they have not loaded — which is the normal state on the\n * very first call, the settings call itself.\n */\n/** Whether `settings` were answered for `activeScopeId` (see {@link resolveThemeVersionId}). */\nfunction answersScope(settings: StoreContext | null | undefined, activeScopeId: string | null) {\n const requestedScopeId = settings?.requestedScopeId ?? null;\n if (activeScopeId == null) return requestedScopeId == null;\n const answeredScopeId = settings?.store?.scope?.id;\n return (answeredScopeId != null ? String(answeredScopeId) : requestedScopeId) === activeScopeId;\n}\n\nexport function resolveThemeVersionId(activeScopeId: string | null = null): string | null {\n const requested = requestedThemeVersionId();\n if (requested) return requested;\n\n try {\n const settings = getTwilightContext().settings;\n if (!answersScope(settings, activeScopeId)) return null;\n\n const profileId = settings?.theme?.profile?.id;\n return profileId != null ? String(profileId) : null;\n } catch {\n return null;\n }\n}\n","export type { StoreContext } from '../api/store';\nimport type { StoreContext } from '../api/store';\nimport type { SallaSDK } from '../types/salla-sdk';\nimport { resolveStoreIdentifier } from './store-identity';\nimport { requestedThemeVersionId } from './theme-version';\n\nconst isBrowser = typeof window !== 'undefined';\n\n/**\n * Which store to ask the API about — see {@link resolveStoreIdentifier}.\n *\n * A delegation, not a second implementation. This name is the one on the wire\n * (`api/client.ts` sets the `store-identifier` header from it) and the one\n * themes import from `@salla.sa/twilight-theme-engine/utils`, so it stays; what\n * it must never do again is answer differently from the resolver everything\n * else asks. It had its own copy of the order once, missing the store the\n * request names and preferring the build-time `VITE_STORE_DOMAIN` that a\n * deployed worker does not have — so every published theme sent an empty\n * identifier and rendered \"Store Unavailable\".\n */\nexport function getStoreIdentifier(explicit?: string): string {\n return resolveStoreIdentifier(explicit);\n}\n\n/**\n * Get Salla SDK instance if available\n */\nexport function getSallaSDK(): typeof window.salla | undefined {\n if (!isBrowser) return undefined;\n return window.salla;\n}\n\n/** Dispatched on `window` by the SDK as the last step of loading (twilight `src/index.js`). */\nconst SDK_CREATED_EVENT = 'salla::created';\n\nconst noop = () => {};\n\n/**\n * Whether `window.salla` is the SDK, rather than the stub that stands in for it.\n *\n * ⚠️ `window.salla` exists from the first bytes of the page. The `twilight-init`\n * head script defines it with an `onReady`, so app snippets can queue work, and\n * the SDK — a deferred module — fills it in later. React can hydrate and run\n * effects in between, and there `window.salla?.event.on(…)` passes its `?.` and\n * throws `Cannot read properties of undefined (reading 'on')`.\n *\n * The SDK defines `init` and `event` in one synchronous module evaluation and the\n * stub has neither, so either one means it has loaded.\n */\nfunction isLoaded(sdk: typeof window.salla): sdk is SallaSDK {\n return typeof sdk?.init === 'function' || typeof sdk?.event?.on === 'function';\n}\n\n/** An SDK whose event bus can take a listener — what {@link onSallaEvent} needs. */\nfunction hasEventBus(sdk: typeof window.salla): sdk is SallaSDK {\n return typeof sdk?.event?.on === 'function';\n}\n\n/**\n * Run `callback` with the SDK as soon as it has loaded: now if it has, otherwise\n * when it announces itself.\n *\n * Returns a cancel for an effect's cleanup, so a component that unmounts first\n * never has the callback run. An effect that returned early when the SDK was not\n * there yet never ran again — on a cold load, where hydration beats the SDK, the\n * engine never initialised it at all.\n */\nexport function whenSallaLoaded(callback: (sdk: SallaSDK) => void): () => void {\n return whenSalla(isLoaded, callback);\n}\n\nfunction whenSalla(\n isUsable: (sdk: typeof window.salla) => sdk is SallaSDK,\n callback: (sdk: SallaSDK) => void\n): () => void {\n if (!isBrowser) return noop;\n\n if (isUsable(window.salla)) {\n callback(window.salla);\n return noop;\n }\n\n let settled = false;\n const onCreated = () => {\n const sdk = window.salla;\n if (settled || !isUsable(sdk)) return;\n settled = true;\n window.removeEventListener(SDK_CREATED_EVENT, onCreated);\n callback(sdk);\n };\n window.addEventListener(SDK_CREATED_EVENT, onCreated);\n\n return () => {\n settled = true;\n window.removeEventListener(SDK_CREATED_EVENT, onCreated);\n };\n}\n\n/**\n * Run `callback` once the SDK has loaded **and been initialised** — for work that\n * talks to the API, which needs the store config `init` sets.\n *\n * Loaded is not enough for that: `init` finishes asynchronously, so a cart lookup\n * made the moment the SDK announces itself goes out without a store identifier\n * and is answered `Store Identifier not found`. Returns a cancel, as\n * {@link whenSallaLoaded} does.\n *\n * A rejected `onReady` still runs `callback`, as `useTwilightInit` carries on past\n * one: it means a partial initialisation, and waiting on it would leave the caller\n * waiting for good.\n */\nexport function whenSallaReady(callback: (sdk: SallaSDK) => void): () => void {\n let cancelled = false;\n const cancel = whenSallaLoaded((sdk) => {\n void new Promise((resolve) => resolve(sdk.onReady?.())).catch(noop).then(() => {\n if (!cancelled) callback(sdk);\n });\n });\n return () => {\n cancelled = true;\n cancel();\n };\n}\n\n/**\n * `salla.event.on(name, listener)` once the SDK has loaded. Returns the matching\n * unsubscribe, which also cancels a subscription still waiting for the SDK.\n *\n * Removed from the emitter it was added to, not from whatever `window.salla` is\n * by the time the component unmounts.\n *\n * Waits for an event bus specifically, not for \"loaded\": an SDK is recognised by\n * `init` alone, and subscribing on one without a bus would throw.\n */\nexport function onSallaEvent(name: string, listener: (...args: unknown[]) => void): () => void {\n let bus: SallaSDK['event'] | undefined;\n const cancel = whenSalla(hasEventBus, (sdk) => {\n bus = sdk.event;\n bus.on(name, listener);\n });\n return () => {\n cancel();\n bus?.off?.(name, listener);\n };\n}\n\n/**\n * Push the active route locale onto the Salla SDK.\n *\n * Why this is needed (and why it must run on every navigation):\n * - The SDK seeds its locale from `navigator.language` — the theme sets no `s-lang`\n * cookie or `window.locale` — so an English browser starts the SDK in `en` even on\n * an `/ar` store.\n * - The SDK fixes its axios `accept-language` header ONCE, at init. `salla.lang.setLocale`\n * only swaps UI translations (it never touches the header), and `salla.init()` is a\n * no-op after `Salla.status === 'ready'`, so the header never refreshes on its own.\n * - `profile::info.fetched` (login / profile refresh on navigation) overrides the header\n * to the *account's* language.\n *\n * Net result without this: `salla.api.*` calls (cart/product details) return data in the\n * wrong locale — e.g. English cart item names on `/ar/cart` — intermittently, depending on\n * load order and whether a profile fetch ran. Re-asserting the URL locale here keeps the\n * header correct. No-op on the server and until the SDK exposes the methods.\n */\nexport function syncSdkLocale(locale: string): void {\n const sdk = getSallaSDK();\n if (!sdk || !locale) return;\n try {\n sdk.lang?.setLocale?.(locale);\n sdk.api?.setHeader?.('accept-language', locale);\n // The localization modal swaps `/${user.language_code}/` in the URL on submit;\n // the SDK never sets this locally, so without it the switch reloads the same page.\n sdk.config?.set?.('user.language_code', locale);\n } catch {\n // SDK partially loaded — the header is re-asserted on the next navigation.\n }\n}\n\n/**\n * The `s-version-id` the SDK sends: the version the request named, else the one\n * the settings report.\n *\n * The request outranks the settings here for the reason it does in\n * `resolveThemeVersionId`. `headers['s-version-id']` is the version the API\n * *answered with*, and for a version it cannot reach it reports the live one\n * while rendering defaults. Read alone, a preview's `salla.api.*` calls asked\n * about the live version while the engine's own asked about the previewed one,\n * so one page showed two versions.\n */\nfunction sdkThemeVersionId(headers: StoreContext['headers']): string | null {\n const versionId = requestedThemeVersionId() ?? headers?.['s-version-id'];\n return versionId != null ? String(versionId) : null;\n}\n\n/**\n * Settings as the SDK's `init` should copy them: with `headers` naming the\n * version {@link sdkThemeVersionId} picks.\n *\n * `init` spreads `headers` over its axios defaults, and on a first load nothing\n * re-asserts the version afterwards: TanStack restores the root match's context\n * instead of re-running `rootBeforeLoad` in the browser, so\n * {@link syncSdkThemeVersion} first runs on a client navigation.\n */\nexport function withSdkThemeVersion<T extends Pick<StoreContext, 'headers'>>(settings: T): T {\n const versionId = requestedThemeVersionId();\n if (!versionId) return settings;\n return { ...settings, headers: { ...settings.headers, 's-version-id': versionId } };\n}\n\n/**\n * Push the theme version onto the Salla SDK: the requested one, else the one the\n * current settings name (see {@link sdkThemeVersionId}).\n *\n * The SDK copies `settings.headers` into its axios defaults ONCE, at init, and\n * `s-version-id` is one of them. Settings refetched on the client — the shopper\n * switched market, and each market has its own version — name a different one,\n * and without this every `salla.api.*` call keeps asking for the previous\n * market's version until a full page load. Settings that name no version take\n * the header off instead, so the SDK asks for the live one like the engine's own\n * client does. No-op on the server and until the SDK exposes its api.\n */\nexport function syncSdkThemeVersion(headers: StoreContext['headers']): void {\n const sdk = getSallaSDK();\n if (!sdk) return;\n const versionId = sdkThemeVersionId(headers);\n try {\n if (versionId != null) sdk.api?.setHeader?.('s-version-id', versionId);\n else delete sdk.api?.axios?.defaults?.headers?.common?.['s-version-id'];\n } catch {\n // SDK partially loaded — the header is re-asserted on the next navigation.\n }\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { advertisement, advertisementsFor } from './chunk-
|
|
1
|
+
import { advertisement, advertisementsFor } from './chunk-VDY3VY7S.js';
|
|
2
2
|
import { useTranslation } from './chunk-TYNZ5B2B.js';
|
|
3
|
-
import { whenSallaReady } from './chunk-
|
|
3
|
+
import { whenSallaReady } from './chunk-XMRNYUQY.js';
|
|
4
4
|
import { subscribeTwilight, getTwilightContext } from './chunk-6K34BCUP.js';
|
|
5
5
|
import { useSyncExternalStore, useState, useEffect } from 'react';
|
|
6
6
|
import { useQuery } from '@tanstack/react-query';
|
|
@@ -99,5 +99,5 @@ function PageAdvertisements() {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
export { PageAdvertisements };
|
|
102
|
-
//# sourceMappingURL=chunk-
|
|
103
|
-
//# sourceMappingURL=chunk-
|
|
102
|
+
//# sourceMappingURL=chunk-YDRURQ2W.js.map
|
|
103
|
+
//# sourceMappingURL=chunk-YDRURQ2W.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/layout/PageAdvertisements.tsx"],"names":[],"mappings":"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","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/components/layout/PageAdvertisements.tsx"],"names":[],"mappings":"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","file":"chunk-YDRURQ2W.js","sourcesContent":["import { useEffect, useState, useSyncExternalStore } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { advertisement, advertisementsFor, type Advertisement } from '../../api/advertisement';\nimport { whenSallaReady } from '../../utils/sdk-helpers';\nimport { useTranslation } from '../../providers/I18nProvider';\nimport { getTwilightContext, subscribeTwilight } from '../../twilight/context';\n\nconst currentPageSlug = () => getTwilightContext().page?.slug;\n\n/** The key `<salla-advertisement>` marks a closed ad with, through `salla.storage` (store.js, JSON). */\nconst dismissedKey = (id: number) => `statusAd-${id}`;\n\n/** Stable while the query has no data, so the effect below doesn't rerun on every render. */\nconst NO_ADS: Advertisement[] = [];\n\n/** Hides the ads this visitor closed before the first paint; the effect then drops them. */\nconst HIDE_DISMISSED_SCRIPT =\n \"(function(){try{if(window.self!==window.top)return;document.currentScript.parentNode.querySelectorAll('.s-advertisement[data-id]').forEach(function(e){if(localStorage.getItem('statusAd-'+e.getAttribute('data-id')))e.hidden=true})}catch(e){}})();\";\n\nfunction isDismissed(id: number): boolean {\n try {\n return Boolean(window.localStorage.getItem(dismissedKey(id)));\n } catch {\n return false;\n }\n}\n\nfunction dismiss(id: number): void {\n const storage = window.salla?.storage;\n if (typeof storage?.set === 'function') storage.set(dismissedKey(id), 'dismissed');\n else {\n try {\n window.localStorage.setItem(dismissedKey(id), JSON.stringify('dismissed'));\n } catch {\n // Storage disabled: the ad hides for this page view only.\n }\n }\n}\n\ninterface ClientView {\n /** The theme editor's iframe, or the SDK's debug flag: every ad shows, closed or not. */\n preview: boolean;\n /** Inside the Salla mobile app, which shows no ads. */\n inApp: boolean;\n dismissed: Set<number>;\n}\n\n/**\n * The merchant's announcement bars, in place of `<salla-advertisement>`. Same data, rules and\n * markup, but rendered on the server (the ads are prefetched in the root `beforeLoad`), so the\n * bar is in the first paint instead of pushing the page down when the web component fetches it.\n */\nexport function PageAdvertisements() {\n const { t } = useTranslation();\n // The deepest route loader's `page`, the page `salla.config` reports.\n const pageSlug = useSyncExternalStore(subscribeTwilight, currentPageSlug, currentPageSlug);\n // The query's `retry: 0` only bounds the server wait; the browser may retry.\n const { data: ads = NO_ADS } = useQuery({ ...advertisement.queries.list(), retry: 2 });\n const [view, setView] = useState<ClientView | null>(null);\n\n useEffect(() => {\n const dismissed = new Set(ads.filter((ad) => isDismissed(ad.id)).map((ad) => ad.id));\n setView({ preview: window.self !== window.top, inApp: false, dismissed });\n return whenSallaReady((sdk) => {\n const config = sdk.config as { isMobileApp?: () => boolean; isDebug?: () => boolean };\n const inApp = Boolean(config?.isMobileApp?.());\n const debug = Boolean(config?.isDebug?.());\n if (inApp || debug) {\n setView((current) =>\n current ? { ...current, inApp, preview: current.preview || debug } : current\n );\n }\n });\n }, [ads]);\n\n if (view?.inApp) return null;\n const shown = view?.preview\n ? ads\n : advertisementsFor(ads, pageSlug).filter((ad) => !view?.dismissed.has(ad.id));\n if (!shown.length) return null;\n\n const close = (id: number) => {\n dismiss(id);\n setView((current) =>\n current ? { ...current, dismissed: new Set(current.dismissed).add(id) } : current\n );\n };\n\n return (\n <>\n {shown.map((ad) => (\n <div\n key={ad.id}\n className=\"s-advertisement\"\n data-id={ad.id}\n style={{ backgroundColor: ad.colors?.bg, color: ad.colors?.text }}\n >\n <div className=\"s-advertisement-content container flex justify-between items-center py-2.5\">\n <span className=\"s-advertisement-content-main flex-1 font-bold text-center text-sm\">\n {/* Rendered without an icon too, as the SDK does: its margin is part of the layout. */}\n <i\n className={`s-advertisement-content-icon inline-block align-middle me-2 text-base ${ad.icon ?? ''}`}\n />\n {ad.url ? (\n <a\n href={ad.url}\n target={ad.target ?? undefined}\n rel={ad.target === '_blank' ? 'noopener' : undefined}\n >\n {ad.description}\n </a>\n ) : (\n ad.description\n )}\n </span>\n <button\n type=\"button\"\n className=\"s-advertisement-action px-1\"\n aria-label={t('common.buttons.close', 'Close')}\n onClick={() => close(ad.id)}\n >\n {/* `inline-block`: before the icon CSS loads, an empty inline `<i>` leaves the button 0px tall. */}\n <i className=\"sicon-cancel inline-block\" />\n </button>\n </div>\n </div>\n ))}\n <script suppressHydrationWarning>{HIDE_DISMISSED_SCRIPT}</script>\n </>\n );\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EMPTY_PREVIEW_STATE, DEV_LOOKUP_TIMEOUT_MS, isEditorFrame, normalizePreviewState, DEV_PREVIEW_GLOBAL, DEV_PREVIEW_EVENT, DEV_PREVIEW_ENDPOINT } from './chunk-OXMUPNMH.js';
|
|
2
|
-
import { resolveStoreBase } from './chunk-
|
|
2
|
+
import { resolveStoreBase } from './chunk-T2752RH7.js';
|
|
3
3
|
import { useSyncExternalStore, useEffect, useRef, useMemo } from 'react';
|
|
4
4
|
|
|
5
5
|
var LEGACY_STORAGE_KEY = "twilight:dev-settings";
|
|
@@ -147,7 +147,7 @@ function takeFrameReport(message) {
|
|
|
147
147
|
async function answerLookup(message) {
|
|
148
148
|
const { requestId, source, query } = message;
|
|
149
149
|
try {
|
|
150
|
-
const { lookupInStore } = await import('./store-lookup-
|
|
150
|
+
const { lookupInStore } = await import('./store-lookup-D5C2LNXK.js');
|
|
151
151
|
sendToEditor({ kind: "lookup-result", requestId, items: await lookupInStore(source, query) });
|
|
152
152
|
} catch (error) {
|
|
153
153
|
sendToEditor({
|
|
@@ -500,5 +500,5 @@ function useDevLayoutBlocks(components) {
|
|
|
500
500
|
var useDevHomeBlocks = import.meta.env.DEV ? useDevLayoutBlocks : (components) => components;
|
|
501
501
|
|
|
502
502
|
export { blockPath, devSettingsStore, useDevEditorMeta, useDevHomeBlocks, useDevReportSettingsFetchedAt, useDevSettingsOverrides, useDevSettingsState };
|
|
503
|
-
//# sourceMappingURL=chunk-
|
|
504
|
-
//# sourceMappingURL=chunk-
|
|
503
|
+
//# sourceMappingURL=chunk-YEBA44IV.js.map
|
|
504
|
+
//# sourceMappingURL=chunk-YEBA44IV.js.map
|