@salla.sa/twilight-theme-engine 1.0.60 → 1.0.61
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-GFAJUB4Y.js → AddToCartForm-RAQX7VHU.js} +3 -3
- package/dist/{AddToCartForm-GFAJUB4Y.js.map → AddToCartForm-RAQX7VHU.js.map} +1 -1
- package/dist/{BlogAuthorPage-WWA75UTA.js → BlogAuthorPage-HV6JUJNL.js} +17 -16
- package/dist/BlogAuthorPage-HV6JUJNL.js.map +1 -0
- package/dist/{BlogCategoryPage-VGIAMWPH.js → BlogCategoryPage-ATPIVUAL.js} +17 -16
- package/dist/BlogCategoryPage-ATPIVUAL.js.map +1 -0
- package/dist/{BlogPage-5MW4WSOH.js → BlogPage-6IIOSB45.js} +15 -14
- package/dist/BlogPage-6IIOSB45.js.map +1 -0
- package/dist/{BlogSinglePage-67E3PVMP.js → BlogSinglePage-DV3XYB26.js} +15 -14
- package/dist/BlogSinglePage-DV3XYB26.js.map +1 -0
- package/dist/{BlogTagPage-EEOIAALL.js → BlogTagPage-RVJIXERD.js} +17 -16
- package/dist/BlogTagPage-RVJIXERD.js.map +1 -0
- package/dist/BrandsPage-RQXP67LV.js +187 -0
- package/dist/BrandsPage-RQXP67LV.js.map +1 -0
- package/dist/{Breadcrumb-4I2HVAFR.js → Breadcrumb-NXXVZJJD.js} +15 -14
- package/dist/Breadcrumb-NXXVZJJD.js.map +1 -0
- package/dist/{CartItem-A7Y6MZXS.js → CartItem-XRWTSJB5.js} +15 -14
- package/dist/CartItem-XRWTSJB5.js.map +1 -0
- package/dist/{CartSummary-MUCVTNKG.js → CartSummary-F6BY5APF.js} +15 -14
- package/dist/CartSummary-F6BY5APF.js.map +1 -0
- package/dist/{Copyright-VJYMP42V.js → Copyright-TEDF6HMC.js} +3 -3
- package/dist/{Copyright-VJYMP42V.js.map → Copyright-TEDF6HMC.js.map} +1 -1
- package/dist/{CustomerLayout-L3Y2TIPF.js → CustomerLayout-T5BSTU6T.js} +15 -14
- package/dist/CustomerLayout-T5BSTU6T.js.map +1 -0
- package/dist/{Footer-OQFU25J4.js → Footer-IRX2WAEF.js} +15 -14
- package/dist/{Footer-OQFU25J4.js.map → Footer-IRX2WAEF.js.map} +1 -1
- package/dist/{Header-QNNAHZJL.js → Header-HQKDTZSI.js} +7 -7
- package/dist/{Header-QNNAHZJL.js.map → Header-HQKDTZSI.js.map} +1 -1
- package/dist/{LoyaltyPage-IULR2XKZ.js → LoyaltyPage-AIUDZLT7.js} +16 -15
- package/dist/LoyaltyPage-AIUDZLT7.js.map +1 -0
- package/dist/{MainMenu-3KKSHFCS.js → MainMenu-4ZPVIJCN.js} +9 -8
- package/dist/MainMenu-4ZPVIJCN.js.map +1 -0
- package/dist/{MasterLayout-HJWMQHWO.js → MasterLayout-G3MVZLYZ.js} +15 -14
- package/dist/{MasterLayout-HJWMQHWO.js.map → MasterLayout-G3MVZLYZ.js.map} +1 -1
- package/dist/{MobileMenu-DBJ23EKX.js → MobileMenu-A5DBTPS7.js} +16 -15
- package/dist/MobileMenu-A5DBTPS7.js.map +1 -0
- package/dist/{NotificationsPage-PUS3WBU6.js → NotificationsPage-T2O67MLD.js} +15 -14
- package/dist/NotificationsPage-T2O67MLD.js.map +1 -0
- package/dist/{OrderSinglePage-4CK6OT6U.js → OrderSinglePage-4W4JZX7I.js} +16 -15
- package/dist/OrderSinglePage-4W4JZX7I.js.map +1 -0
- package/dist/{OrdersPage-EGIDHSYS.js → OrdersPage-DYKFBMRC.js} +16 -15
- package/dist/OrdersPage-DYKFBMRC.js.map +1 -0
- package/dist/{PageSingle-ORPH52QX.js → PageSingle-6U6GPMXJ.js} +3 -3
- package/dist/{PageSingle-ORPH52QX.js.map → PageSingle-6U6GPMXJ.js.map} +1 -1
- package/dist/{ProductDetails-RY6PNKKJ.js → ProductDetails-OWSIL357.js} +3 -3
- package/dist/{ProductDetails-RY6PNKKJ.js.map → ProductDetails-OWSIL357.js.map} +1 -1
- package/dist/{ProfilePage-IO2MDE53.js → ProfilePage-LLCIJHAI.js} +15 -14
- package/dist/ProfilePage-LLCIJHAI.js.map +1 -0
- package/dist/{SeoCartWidget-TPSVEGMI.js → SeoCartWidget-ZL3FTBWK.js} +15 -14
- package/dist/SeoCartWidget-ZL3FTBWK.js.map +1 -0
- package/dist/{SettingsPage-ZTD4ALAA.js → SettingsPage-2XU5IF4A.js} +15 -14
- package/dist/SettingsPage-2XU5IF4A.js.map +1 -0
- package/dist/{StoreClosedNotification-52REE2T5.js → StoreClosedNotification-CNJI2Q26.js} +16 -15
- package/dist/{StoreClosedNotification-52REE2T5.js.map → StoreClosedNotification-CNJI2Q26.js.map} +1 -1
- package/dist/{TestimonialsPage-QDBHJADT.js → TestimonialsPage-QYPLMNWL.js} +3 -3
- package/dist/{TestimonialsPage-QDBHJADT.js.map → TestimonialsPage-QYPLMNWL.js.map} +1 -1
- package/dist/{ThankYouPage-IRLZI3HI.js → ThankYouPage-WG3CM5JP.js} +15 -14
- package/dist/ThankYouPage-WG3CM5JP.js.map +1 -0
- package/dist/{WalletPage-ZTSSGFMO.js → WalletPage-J7CH22JM.js} +16 -15
- package/dist/WalletPage-J7CH22JM.js.map +1 -0
- package/dist/{WishlistPage-OADS7B5J.js → WishlistPage-ZXWYB56R.js} +17 -16
- package/dist/WishlistPage-ZXWYB56R.js.map +1 -0
- package/dist/api/apps.js +6 -5
- package/dist/api/brands.d.ts +6 -5
- package/dist/api/brands.d.ts.map +1 -1
- package/dist/api/brands.js +7 -6
- package/dist/api/cart.js +7 -6
- package/dist/api/category.js +7 -6
- package/dist/api/client.js +5 -4
- package/dist/api/home.js +6 -5
- package/dist/api/loyalty.js +7 -6
- package/dist/api/menu.js +6 -5
- package/dist/api/notification.js +6 -5
- package/dist/api/order.js +7 -6
- package/dist/api/page.js +7 -6
- package/dist/api/product.js +7 -6
- package/dist/api/profile.js +5 -4
- package/dist/api/profile.js.map +1 -1
- package/dist/api/store.js +6 -5
- package/dist/api/translations.js +6 -5
- package/dist/api/user.js +6 -5
- package/dist/api/wishlist.js +8 -7
- package/dist/{chunk-ANWDPISS.js → chunk-2U3PUO3V.js} +18 -16
- package/dist/chunk-2U3PUO3V.js.map +1 -0
- package/dist/{chunk-YGDAYFQY.js → chunk-2XGQSJKH.js} +3 -3
- package/dist/{chunk-YGDAYFQY.js.map → chunk-2XGQSJKH.js.map} +1 -1
- package/dist/{chunk-J7BQY4ZK.js → chunk-3ITQB3PY.js} +4 -4
- package/dist/{chunk-J7BQY4ZK.js.map → chunk-3ITQB3PY.js.map} +1 -1
- package/dist/{chunk-IFWQTDEY.js → chunk-3YVAYIM4.js} +6 -6
- package/dist/{chunk-IFWQTDEY.js.map → chunk-3YVAYIM4.js.map} +1 -1
- package/dist/{chunk-K34A2LBY.js → chunk-4DHLIY6V.js} +4 -4
- package/dist/{chunk-K34A2LBY.js.map → chunk-4DHLIY6V.js.map} +1 -1
- package/dist/{chunk-KZMUU5ZD.js → chunk-5X2UFNKY.js} +3 -3
- package/dist/{chunk-KZMUU5ZD.js.map → chunk-5X2UFNKY.js.map} +1 -1
- package/dist/{chunk-S7JSNUU2.js → chunk-5ZR2HKZ7.js} +3 -3
- package/dist/{chunk-S7JSNUU2.js.map → chunk-5ZR2HKZ7.js.map} +1 -1
- package/dist/{chunk-UQAUDOI7.js → chunk-6IDCWH5K.js} +10 -7
- package/dist/chunk-6IDCWH5K.js.map +1 -0
- package/dist/{chunk-GXXWHVLS.js → chunk-7OIP65ER.js} +5 -5
- package/dist/{chunk-GXXWHVLS.js.map → chunk-7OIP65ER.js.map} +1 -1
- package/dist/{chunk-ICPO2ELD.js → chunk-EAZGFREP.js} +3 -3
- package/dist/{chunk-ICPO2ELD.js.map → chunk-EAZGFREP.js.map} +1 -1
- package/dist/{chunk-GX3EDS32.js → chunk-FUIPNVQY.js} +6 -6
- package/dist/{chunk-GX3EDS32.js.map → chunk-FUIPNVQY.js.map} +1 -1
- package/dist/{chunk-T63KKKW2.js → chunk-GUGZ4CEG.js} +4 -4
- package/dist/{chunk-T63KKKW2.js.map → chunk-GUGZ4CEG.js.map} +1 -1
- package/dist/{chunk-6LIGRH4O.js → chunk-IZFZLJHD.js} +5 -5
- package/dist/{chunk-6LIGRH4O.js.map → chunk-IZFZLJHD.js.map} +1 -1
- package/dist/{chunk-KRCPBXFJ.js → chunk-JVGZDLFP.js} +4 -4
- package/dist/{chunk-KRCPBXFJ.js.map → chunk-JVGZDLFP.js.map} +1 -1
- package/dist/{chunk-GZKCZ6X7.js → chunk-LCJW7JKZ.js} +5 -5
- package/dist/{chunk-GZKCZ6X7.js.map → chunk-LCJW7JKZ.js.map} +1 -1
- package/dist/{chunk-OGQXRBCR.js → chunk-N2S25NXP.js} +37 -9
- package/dist/chunk-N2S25NXP.js.map +1 -0
- package/dist/{chunk-R2ULWW5T.js → chunk-N4THXNXA.js} +28 -21
- package/dist/chunk-N4THXNXA.js.map +1 -0
- package/dist/{chunk-NYD5Z4RJ.js → chunk-NFTOMTTI.js} +4 -4
- package/dist/{chunk-NYD5Z4RJ.js.map → chunk-NFTOMTTI.js.map} +1 -1
- package/dist/{chunk-R3TPJHLI.js → chunk-NHKP5XIG.js} +4 -4
- package/dist/{chunk-R3TPJHLI.js.map → chunk-NHKP5XIG.js.map} +1 -1
- package/dist/{chunk-NOB7OWFA.js → chunk-NQVJ7NJ6.js} +3 -3
- package/dist/{chunk-NOB7OWFA.js.map → chunk-NQVJ7NJ6.js.map} +1 -1
- package/dist/{chunk-NKLKKZM6.js → chunk-OET4G4XC.js} +3 -3
- package/dist/{chunk-NKLKKZM6.js.map → chunk-OET4G4XC.js.map} +1 -1
- package/dist/{chunk-BHU25UEW.js → chunk-P3OPJL6I.js} +6 -5
- package/dist/chunk-P3OPJL6I.js.map +1 -0
- package/dist/{chunk-B3EFOE57.js → chunk-PK7EU5TM.js} +2 -2
- package/dist/chunk-PK7EU5TM.js.map +1 -0
- package/dist/{chunk-ZOZLNUNA.js → chunk-Q3COPV5Z.js} +4 -4
- package/dist/{chunk-ZOZLNUNA.js.map → chunk-Q3COPV5Z.js.map} +1 -1
- package/dist/{chunk-YGSU36MZ.js → chunk-RJAVZBUK.js} +3 -3
- package/dist/{chunk-YGSU36MZ.js.map → chunk-RJAVZBUK.js.map} +1 -1
- package/dist/{chunk-XTMHHLNK.js → chunk-SR4OTLTJ.js} +23 -5
- package/dist/chunk-SR4OTLTJ.js.map +1 -0
- package/dist/{chunk-HAV32VZS.js → chunk-TDZSHACC.js} +30 -5
- package/dist/chunk-TDZSHACC.js.map +1 -0
- package/dist/{chunk-CUX7O42G.js → chunk-TLAEW7TB.js} +3 -3
- package/dist/{chunk-CUX7O42G.js.map → chunk-TLAEW7TB.js.map} +1 -1
- package/dist/{chunk-NK2V2SW5.js → chunk-TLO2M5TJ.js} +5 -5
- package/dist/{chunk-NK2V2SW5.js.map → chunk-TLO2M5TJ.js.map} +1 -1
- package/dist/{chunk-T26Y47JL.js → chunk-TTMYT3RB.js} +4 -4
- package/dist/{chunk-T26Y47JL.js.map → chunk-TTMYT3RB.js.map} +1 -1
- package/dist/{chunk-VRV5F6G7.js → chunk-TYLKNVQA.js} +5 -25
- package/dist/chunk-TYLKNVQA.js.map +1 -0
- package/dist/{chunk-X7P2WSNU.js → chunk-UIOLSYKV.js} +3 -3
- package/dist/{chunk-X7P2WSNU.js.map → chunk-UIOLSYKV.js.map} +1 -1
- package/dist/{chunk-6DVYW7OA.js → chunk-UZKTK6YV.js} +4 -4
- package/dist/{chunk-6DVYW7OA.js.map → chunk-UZKTK6YV.js.map} +1 -1
- package/dist/{chunk-HF6RCUMD.js → chunk-VJHDE6UT.js} +4 -4
- package/dist/{chunk-HF6RCUMD.js.map → chunk-VJHDE6UT.js.map} +1 -1
- package/dist/{chunk-AODO3GFK.js → chunk-VSJLPWFI.js} +4 -4
- package/dist/{chunk-AODO3GFK.js.map → chunk-VSJLPWFI.js.map} +1 -1
- package/dist/{chunk-JDDQHFIW.js → chunk-W2B5P54C.js} +4 -4
- package/dist/{chunk-JDDQHFIW.js.map → chunk-W2B5P54C.js.map} +1 -1
- package/dist/{chunk-RLSYCDI4.js → chunk-WH225GEC.js} +26 -11
- package/dist/chunk-WH225GEC.js.map +1 -0
- package/dist/chunk-WY4IYO3G.js +25 -0
- package/dist/chunk-WY4IYO3G.js.map +1 -0
- package/dist/{chunk-WPHI6Q6N.js → chunk-YH4O3H4R.js} +4 -4
- package/dist/{chunk-WPHI6Q6N.js.map → chunk-YH4O3H4R.js.map} +1 -1
- package/dist/chunk-ZPRZQTYM.js +14 -0
- package/dist/{chunk-6EES4C7J.js.map → chunk-ZPRZQTYM.js.map} +1 -1
- package/dist/chunk-ZQGMVUPE.js +29 -0
- package/dist/chunk-ZQGMVUPE.js.map +1 -0
- package/dist/components/cart/index.js +1 -1
- package/dist/components/common/index.js +1 -1
- package/dist/components/drawer/index.js +13 -12
- package/dist/components/home/index.js +16 -15
- package/dist/components/layout/index.js +5 -5
- package/dist/components/product/index.js +14 -13
- package/dist/components/store/index.js +15 -14
- package/dist/components/store/index.js.map +1 -1
- package/dist/document-class-7KPUN2DK.js +26 -0
- package/dist/{document-class-SX2LHILG.js.map → document-class-7KPUN2DK.js.map} +1 -1
- package/dist/hooks/index.js +13 -12
- package/dist/hooks/useGtm.js +13 -12
- package/dist/hooks/useMoney.js +13 -12
- package/dist/hooks/useStore.js +13 -12
- package/dist/hooks/useUser.js +7 -6
- package/dist/index.js +13 -12
- package/dist/index.js.map +1 -1
- package/dist/navigation-QMBOIYJI.js +12 -0
- package/dist/{navigation-Z6JMJ4FZ.js.map → navigation-QMBOIYJI.js.map} +1 -1
- package/dist/{navigation-7WGWEDLB.js → navigation-XZJCQXY3.js} +5 -5
- package/dist/{navigation-7WGWEDLB.js.map → navigation-XZJCQXY3.js.map} +1 -1
- package/dist/{not-found-CDXSWL7T.js → not-found-UE5XOV5C.js} +16 -15
- package/dist/not-found-UE5XOV5C.js.map +1 -0
- package/dist/providers/NavigationProvider.d.ts +5 -5
- package/dist/providers/NavigationProvider.d.ts.map +1 -1
- package/dist/providers/TwilightProvider.d.ts.map +1 -1
- package/dist/providers/index.js +13 -12
- package/dist/routes/account/notifications/loader.d.ts.map +1 -1
- package/dist/routes/account/orders/loader.d.ts.map +1 -1
- package/dist/routes/account/orders.js +8 -7
- package/dist/routes/account/profile/loader.d.ts.map +1 -1
- package/dist/routes/account/settings/loader.d.ts.map +1 -1
- package/dist/routes/account/wallet/loader.d.ts.map +1 -1
- package/dist/routes/account/wishlist/loader.d.ts.map +1 -1
- package/dist/routes/account.js +24 -20
- package/dist/routes/account.js.map +1 -1
- package/dist/routes/blog.js +12 -11
- package/dist/routes/blog.js.map +1 -1
- package/dist/routes/brands/BrandsPage.d.ts +1 -1
- package/dist/routes/brands/BrandsPage.d.ts.map +1 -1
- package/dist/routes/brands/index.d.ts +2 -2
- package/dist/routes/brands/index.d.ts.map +1 -1
- package/dist/routes/brands/loader.d.ts.map +1 -1
- package/dist/routes/brands/types.d.ts +4 -1
- package/dist/routes/brands/types.d.ts.map +1 -1
- package/dist/routes/brands.js +12 -22
- package/dist/routes/brands.js.map +1 -1
- package/dist/routes/cart.js +21 -20
- package/dist/routes/cart.js.map +1 -1
- package/dist/routes/home.js +18 -17
- package/dist/routes/index.js +4 -4
- package/dist/routes/lazy.d.ts +1 -1
- package/dist/routes/lazy.d.ts.map +1 -1
- package/dist/routes/loyalty/index.d.ts +1 -1
- package/dist/routes/loyalty/index.d.ts.map +1 -1
- package/dist/routes/loyalty/loader.d.ts +1 -1
- package/dist/routes/loyalty/loader.d.ts.map +1 -1
- package/dist/routes/loyalty.js +21 -12
- package/dist/routes/loyalty.js.map +1 -1
- package/dist/routes/page.js +8 -7
- package/dist/routes/page.js.map +1 -1
- package/dist/routes/product-listing.js +18 -17
- package/dist/routes/product-listing.js.map +1 -1
- package/dist/routes/product.js +16 -15
- package/dist/routes/product.js.map +1 -1
- package/dist/routes/seo-redirects.js +4 -4
- package/dist/routes/testimonials.js +2 -2
- package/dist/routes/thank-you.js +8 -7
- package/dist/routes/thank-you.js.map +1 -1
- package/dist/skeleton.js +18 -17
- package/dist/tanstack/navigation.d.ts.map +1 -1
- package/dist/tanstack.js +19 -28
- package/dist/tanstack.js.map +1 -1
- package/dist/twilight/context.d.ts.map +1 -1
- package/dist/utils/cookies.d.ts +7 -0
- package/dist/utils/cookies.d.ts.map +1 -1
- package/dist/utils/head.d.ts +3 -0
- package/dist/utils/head.d.ts.map +1 -1
- package/dist/utils/head.js +1 -1
- package/dist/utils/index.js +7 -6
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/request-host.d.ts +2 -8
- package/dist/utils/request-host.d.ts.map +1 -1
- package/dist/utils/store-base.d.ts +11 -0
- package/dist/utils/store-base.d.ts.map +1 -1
- package/dist/vite/index.js +3 -3
- package/package.json +1 -1
- package/dist/BlogAuthorPage-WWA75UTA.js.map +0 -1
- package/dist/BlogCategoryPage-VGIAMWPH.js.map +0 -1
- package/dist/BlogPage-5MW4WSOH.js.map +0 -1
- package/dist/BlogSinglePage-67E3PVMP.js.map +0 -1
- package/dist/BlogTagPage-EEOIAALL.js.map +0 -1
- package/dist/BrandsPage-SNVIBZGR.js +0 -132
- package/dist/BrandsPage-SNVIBZGR.js.map +0 -1
- package/dist/Breadcrumb-4I2HVAFR.js.map +0 -1
- package/dist/CartItem-A7Y6MZXS.js.map +0 -1
- package/dist/CartSummary-MUCVTNKG.js.map +0 -1
- package/dist/CustomerLayout-L3Y2TIPF.js.map +0 -1
- package/dist/LoyaltyPage-IULR2XKZ.js.map +0 -1
- package/dist/MainMenu-3KKSHFCS.js.map +0 -1
- package/dist/MobileMenu-DBJ23EKX.js.map +0 -1
- package/dist/NotificationsPage-PUS3WBU6.js.map +0 -1
- package/dist/OrderSinglePage-4CK6OT6U.js.map +0 -1
- package/dist/OrdersPage-EGIDHSYS.js.map +0 -1
- package/dist/ProfilePage-IO2MDE53.js.map +0 -1
- package/dist/SeoCartWidget-TPSVEGMI.js.map +0 -1
- package/dist/SettingsPage-ZTD4ALAA.js.map +0 -1
- package/dist/ThankYouPage-IRLZI3HI.js.map +0 -1
- package/dist/WalletPage-ZTSSGFMO.js.map +0 -1
- package/dist/WishlistPage-OADS7B5J.js.map +0 -1
- package/dist/chunk-6EES4C7J.js +0 -14
- package/dist/chunk-ANWDPISS.js.map +0 -1
- package/dist/chunk-AVUX6GAG.js +0 -29
- package/dist/chunk-AVUX6GAG.js.map +0 -1
- package/dist/chunk-B3EFOE57.js.map +0 -1
- package/dist/chunk-BHU25UEW.js.map +0 -1
- package/dist/chunk-HAV32VZS.js.map +0 -1
- package/dist/chunk-OGQXRBCR.js.map +0 -1
- package/dist/chunk-R2ULWW5T.js.map +0 -1
- package/dist/chunk-RLSYCDI4.js.map +0 -1
- package/dist/chunk-UQAUDOI7.js.map +0 -1
- package/dist/chunk-VRV5F6G7.js.map +0 -1
- package/dist/chunk-XTMHHLNK.js.map +0 -1
- package/dist/document-class-SX2LHILG.js +0 -25
- package/dist/navigation-Z6JMJ4FZ.js +0 -11
- package/dist/not-found-CDXSWL7T.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/routes/root/beforeLoad.ts","../src/routes/root/head.ts","../src/tanstack/store-base.ts","../src/tanstack/router.tsx","../src/tanstack/document-class.ts"],"names":["store","createTanStackRouter"],"mappings":"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","file":"chunk-R2ULWW5T.js","sourcesContent":["import type { QueryClient } from '@tanstack/react-query';\nimport { redirect } from '@tanstack/react-router';\nimport { createIsomorphicFn } from '@tanstack/react-start';\nimport { getCookie } from '@tanstack/react-start/server';\nimport type { StoreContext } from '../../api/store';\nimport { store as storeApi } from '../../api/store';\nimport { apps, type AppSnippet, type AppSettings } from '../../api/apps';\nimport { translations } from '../../api/translations';\nimport { FALLBACK_LOCALE, getLanguageInfo } from '../../providers/locale-constants';\nimport { createI18nInstance } from '../../providers/i18n-factory';\nimport type { TwilightLocation } from '../../twilight/context';\nimport { getTwilightContext, updateTwilightContext } from '../../twilight/context';\nimport {\n AUTH_TOKEN_COOKIE_NAME,\n extractTokenFromCookies,\n syncScopeCookie,\n} from '../../utils/cookies';\nimport { syncSdkLocale } from '../../utils/sdk-helpers';\nimport { SettingsError } from '../../utils/errors';\nimport { resolveStoreBaseRedirect } from '../../utils/store-identity';\n\n// Reads the `token` cookie from the incoming request on the SERVER. twilightMiddleware\n// extracts the same cookie into a custom ALS, but that ALS does NOT propagate to the\n// route's beforeLoad / React SSR render (they run in a different async scope), so the\n// token must be read again here from the framework's own request context. On the client\n// this is a no-op (the cookie is read from document.cookie below instead). The server\n// import is stripped from the client bundle by createIsomorphicFn.\nconst readServerCookieToken = createIsomorphicFn()\n .server((): string | null => {\n try {\n return getCookie(AUTH_TOKEN_COOKIE_NAME) ?? null;\n } catch {\n return null;\n }\n })\n .client((): string | null => null);\n\nexport interface BeforeLoadResult {\n settings: StoreContext;\n locale: string;\n dir: 'ltr' | 'rtl';\n authToken: string | null;\n /** Installed apps' snippets, threaded through the beforeLoad context (and recovered on the\n * client via ensureTwilightContextFromMatches) so AppsSnippets can render CDN tags in SSR. */\n appsSnippets?: AppSnippet[];\n /** Per-app public `app.*` buckets, threaded the same way so rootHead can install the\n * `Salla.appScope` factory inline in the SSR head. */\n appsSettings?: AppSettings;\n}\n\n/**\n * The platform's copy for `locale`, with this merchant's own wording over it.\n *\n * Returns the platform's copy untouched — and makes no request — unless the\n * settings say this language has overrides. That gate is the whole reason this\n * is affordable: the object 404s for most stores, uncached, on the critical\n * path of an SSR render.\n *\n * The entry is found by ISO code rather than by index or key. The API sends\n * `languages` as an object keyed by **upper-case** ISO, and `storeApi` converts\n * it to an array on the way through (`languagesToArray`), so neither the\n * upper-case key nor a position is available here — and matching case-sensitively\n * on `code` would be a lookup that misses silently, leaving the flag absent and\n * the feature simply never running.\n *\n * Nothing about this is fatal. A failed override read leaves the platform's\n * copy in place, which is a storefront in the words Salla ships rather than a\n * storefront that did not render.\n */\nasync function withMerchantTranslations(\n queryClient: QueryClient,\n settings: StoreContext,\n locale: string,\n common: Awaited<ReturnType<typeof translations.get>>\n): Promise<Awaited<ReturnType<typeof translations.get>>> {\n const wanted = locale.toLowerCase();\n const language = settings.languages?.find(\n (entry) => (entry.iso_code ?? entry.code)?.toLowerCase() === wanted\n );\n const storeId = settings.store?.id;\n\n if (!language?.has_custom_translations || !storeId) return common;\n\n try {\n const overrides = await queryClient.ensureQueryData(\n translations.queries.byStore(storeId, locale)\n );\n\n return translations.merge(common, overrides, locale);\n } catch (error) {\n console.warn('[salla] merchant translations could not be read; using the platform copy', error);\n return common;\n }\n}\n\nexport async function rootBeforeLoad(ctx: {\n params: Record<string, string>;\n location: TwilightLocation;\n context: {\n queryClient: QueryClient;\n setLocation?: (location: Partial<TwilightLocation>) => void;\n };\n serverContext?: {\n authToken?: string | null;\n };\n}): Promise<BeforeLoadResult> {\n const locale = ctx.params.locale || FALLBACK_LOCALE;\n const { dir } = getLanguageInfo(locale);\n\n if (ctx.context.setLocation) {\n ctx.context.setLocation(ctx.location);\n }\n\n // Set locale in context before any API calls so interceptor uses correct locale\n updateTwilightContext({ locale });\n\n // Re-assert the locale on the Salla SDK on every navigation. The SDK's axios\n // accept-language header drifts off the route locale (navigator.language default,\n // account-language override on profile fetch — see syncSdkLocale), which makes\n // SDK API calls (e.g. the cart's salla.api.cart.details) return wrong-locale data.\n syncSdkLocale(locale);\n\n // Mirror the SDK's selected branch into the `scope` cookie. The SDK persists the\n // selection in localStorage ONLY, so the server — which can only see cookies —\n // would otherwise compute scope=null for every visitor who picked a branch, and\n // the dehydrated settings query (keyed on the scope) would never match on the\n // client. No-op on the server and while the SDK storage API is still hydrating.\n syncScopeCookie();\n\n const [settingsResult, translationsResult, snippetsResult, appSettingsResult] = await Promise.all(\n [\n ctx.context.queryClient.ensureQueryData(storeApi.queries.settings()),\n ctx.context.queryClient.ensureQueryData(translations.queries.byLocale(locale)),\n // Snippets → SSR CDN <script> tags (AppsSnippets.ssrCdnScripts). Non-fatal + logged:\n // on failure AppsSnippets falls back to its own client-side query for the same data,\n // so the tags render a paint later instead of being lost for the page load.\n ctx.context.queryClient.ensureQueryData(apps.queries.snippets()).catch((error): undefined => {\n console.warn('[salla] apps/snippets prefetch failed; rendering no CDN snippet tags', error);\n return undefined;\n }),\n // Buckets → rootHead installs `Salla.appScope` inline in the SSR head (before any snippet\n // onReady runs). Non-fatal + logged: the head installs the factory either way, and the\n // client query seeds the buckets into that install once it resolves.\n ctx.context.queryClient.ensureQueryData(apps.queries.settings()).catch((error): undefined => {\n console.warn(\n '[salla] apps/snippets/settings prefetch failed; appScope buckets unseeded',\n error\n );\n return undefined;\n }),\n ]\n );\n\n if (!settingsResult) {\n throw new SettingsError('Failed to load store settings. Make sure VITE_STORE_DOMAIN is set.');\n }\n\n // On a host where the store is the root of every URL, a page has one address:\n // `/<username>/…`. A request that found its store some other way (`?storeId=`,\n // the preview cookie, `VITE_STORE_DOMAIN`) is sent there now that the settings\n // say what the username is. A full load rather than a client navigation, because\n // the router handling this request was built without that root.\n const storeBaseHref = resolveStoreBaseRedirect(settingsResult.store?.username, ctx.location.href);\n if (storeBaseHref) {\n throw redirect({ href: storeBaseHref, reloadDocument: true, replace: true });\n }\n\n // The merchant's own wording, laid over the platform's — but only when the\n // settings say this language has any.\n //\n // Sequenced after the `Promise.all` on purpose: the object is keyed by\n // `settings.store.id`, which the settings query is what produces, so this\n // cannot join the batch above. The cost of a second round trip is why it is\n // gated rather than always fetched — see `api/translations.ts` for the two\n // corrections that shape led to.\n const messages = await withMerchantTranslations(\n ctx.context.queryClient,\n settingsResult,\n locale,\n translationsResult\n );\n\n // Create i18n instance with loaded translations\n const i18n = createI18nInstance(locale, messages ?? undefined);\n\n // Resolve authToken with fallback chain:\n // 1. SSR context (from middleware extracting cookies on server)\n // 2. The twilight context token. On the SERVER this is the token twilightMiddleware\n // extracted from the `token` cookie into the request ALS — reading it here is\n // essential, otherwise this loader's updateTwilightContext() below would\n // overwrite the middleware's token with null and every SSR render (e.g. the\n // account hub) would be unauthenticated. On the CLIENT it's the clientStore\n // token from hydration or a previous navigation.\n // 3. The `token` cookie read directly — client fallback when clientStore is empty\n // and salla.storage hasn't hydrated yet.\n // 4. Salla SDK storage (salla.storage.get('token'))\n let existingToken: string | null = null;\n try {\n existingToken = getTwilightContext().authToken;\n } catch {\n // No request context (e.g. server call outside the middleware ALS) — fall through.\n existingToken = null;\n }\n const cookieToken =\n typeof document !== 'undefined'\n ? extractTokenFromCookies(document.cookie, AUTH_TOKEN_COOKIE_NAME)\n : null;\n const sallaToken =\n typeof window !== 'undefined' && window.salla && typeof window.salla.storage.get === 'function'\n ? (window.salla.storage.get(AUTH_TOKEN_COOKIE_NAME) as string | null)\n : null;\n const serverCookieToken = readServerCookieToken();\n const authToken =\n ctx.serverContext?.authToken ??\n serverCookieToken ??\n existingToken ??\n cookieToken ??\n sallaToken ??\n null;\n\n updateTwilightContext({\n queryClient: ctx.context.queryClient,\n settings: settingsResult,\n locale,\n location: ctx.location,\n i18n,\n authToken,\n appsSnippets: snippetsResult,\n appsSettings: appSettingsResult,\n });\n\n return {\n settings: settingsResult,\n locale,\n dir,\n authToken,\n appsSnippets: snippetsResult,\n appsSettings: appSettingsResult,\n };\n}\n","import type { HeadDescriptor, HeadResult } from '../../utils/head';\nimport { mergeHead, resolveHead } from '../../utils/head';\nimport { buildBaseHead } from '../../utils/baseHead';\nimport { FALLBACK_LOCALE } from '../../providers/locale-constants';\nimport { getTwilightContext } from '../../twilight/context';\nimport type { TwilightContextMatch } from '../../twilight/ensure-context';\nimport { ensureTwilightContextFromMatches } from '../../twilight/ensure-context';\nimport type { StoreContext } from '../../api/store';\nimport type { AppSnippet } from '../../api/apps';\nimport { SettingsError } from '../../utils/errors';\nimport { renderAppScopeInstallScript } from '../../utils/app-scope';\nimport { renderThemeHookSlotsScript } from '../../utils/theme-hook-slots';\nimport { escapeForInlineScript } from '../../utils/inline-script';\nimport { readEnv, renderRuntimeEnvScript } from '../../utils/runtime-env';\n\nconst SALLA_ICONS_CSS_URL = 'https://cdn.assets.salla.network/static/fonts/sallaicons.css?v=2.0.5';\nconst LIT_VERSION = '3.3.3';\nconst LIT_CDN_BASE = `https://cdn.assets.salla.network/static/lit/${LIT_VERSION}`;\n\n/** Bare-specifier map for the lit build the engine's `<salla-*>` web components resolve against. */\nconst LIT_IMPORTS: Record<string, string> = {\n lit: `${LIT_CDN_BASE}/lit.js`,\n 'lit/': `${LIT_CDN_BASE}/`,\n 'lit-html': `${LIT_CDN_BASE}/lit-html/lit-html.js`,\n 'lit-html/': `${LIT_CDN_BASE}/lit-html/`,\n 'lit-element': `${LIT_CDN_BASE}/lit-element/lit-element.js`,\n 'lit-element/': `${LIT_CDN_BASE}/lit-element/`,\n '@lit/reactive-element': `${LIT_CDN_BASE}/reactive-element/reactive-element.js`,\n '@lit/reactive-element/': `${LIT_CDN_BASE}/reactive-element/`,\n};\n\nconst TWILIGHT_RELEASE_CDN = 'https://cdn.salla.network/js/twilight';\nconst TWILIGHT_DEV_CDN = 'https://cdn.assets.salla.network/dev/@salla.sa/twilight';\n// The oldest Twilight release this engine works with. Raise it whenever the engine\n// starts relying on something newer; the reason lives in that commit. Today's floor:\n// components ship their own CSS, which themes no longer compile (SallaApp/twilight#2107).\nconst MIN_TWILIGHT_VERSION = '2.14.538';\n// Last resort when no override and no platform pin, and the substitute for a pin below the floor.\nconst DEFAULT_TWILIGHT_VERSION = '2.14.584';\nconst releaseUrl = (version: string): string =>\n `${TWILIGHT_RELEASE_CDN}/${version}/twilight.esm.js`;\n// The head is built more than once per request (early hints, then the page); say it once.\nconst warnedPins = new Set<string>();\n\n/** `x.y.z` release pins only; dev shas and other strings are loaded as given. */\nfunction belowMinimum(version: string): boolean {\n return (\n /^\\d+\\.\\d+\\.\\d+$/.test(version) &&\n version.localeCompare(MIN_TWILIGHT_VERSION, undefined, { numeric: true }) < 0\n );\n}\n\n/**\n * Which twilight.esm.js the storefront loads, in priority order:\n * 1. `VITE_TWILIGHT_URL` — full local/deployment override.\n * 2. `VITE_TWILIGHT_VERSION` — dev-CDN build override.\n * 3. `theme.twilight.version` from the settings endpoint — the platform-pinned\n * release used when no environment override is configured.\n * 4. The engine's default release, also used when the pin is below the engine minimum.\n */\nexport function resolveTwilightSdkUrl(settings?: StoreContext): string {\n const urlOverride = readEnv('VITE_TWILIGHT_URL');\n if (urlOverride) return urlOverride;\n\n const versionOverride = readEnv('VITE_TWILIGHT_VERSION');\n if (versionOverride) return `${TWILIGHT_DEV_CDN}/${versionOverride}/twilight.esm.js`;\n\n const pinnedVersion = settings?.theme?.twilight?.version;\n if (pinnedVersion && belowMinimum(pinnedVersion)) {\n if (!warnedPins.has(pinnedVersion)) {\n warnedPins.add(pinnedVersion);\n console.warn(\n `[twilight] theme.twilight.version ${pinnedVersion} is below the engine minimum ${MIN_TWILIGHT_VERSION}; loading ${DEFAULT_TWILIGHT_VERSION} instead`\n );\n }\n return releaseUrl(DEFAULT_TWILIGHT_VERSION);\n }\n if (pinnedVersion) return releaseUrl(pinnedVersion);\n\n return releaseUrl(DEFAULT_TWILIGHT_VERSION);\n}\n\nconst MEDIA_SWAP_SCRIPT = `\n(function(){var e=function(t){var l=document.getElementById(t);if(l){if(l.sheet||\"all\"===l.media)l.media=\"all\";else l.onload=function(){this.media=\"all\"}}};e(\"salla-theme-font\");e(\"salla-icons-css\")})();\n`.trim();\n\nconst LOADING_CSS = `\n.loading-overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;background:#fff;z-index:9999}\n.loading-spinner{animation:spin 1s linear infinite;border-radius:9999px;height:3rem;width:3rem;border-bottom:2px solid var(--color-primary,#000)}\n@keyframes spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}\nhtml,body{margin:0;padding:0;height:100%}\n`.trim();\n\nconst SALLA_INIT_SCRIPT = `\nwindow.salla = window.Salla = window.Salla || window.salla || {};\nwindow.Salla.onReady = window.Salla.onReady || function(callback) {\n return new Promise(function(resolve) {\n if (window.Salla.status === 'ready') {\n var config = window.salla && window.salla.config && window.salla.config.all();\n resolve(callback ? callback(config) : config);\n } else {\n window.addEventListener('twilight::initiated', function(event) {\n resolve(callback ? callback(event.detail) : event.detail);\n }, { once: true });\n }\n });\n};\n`.trim();\n\n/**\n * Distinct snippet-host origins to `preconnect` (warm DNS/TCP/TLS during parse). From the real\n * URLs (dev/prod-correct), deduped and capped at 4. No `crossOrigin`: snippets are no-cors fetches.\n */\nexport function snippetPreconnectOrigins(snippets: readonly AppSnippet[] | undefined): string[] {\n if (!snippets?.length) return [];\n const origins = new Set<string>();\n for (const app of snippets) {\n if (app.status !== 'enabled') continue;\n for (const s of app.snippets) {\n if (!s.url) continue;\n try {\n origins.add(new URL(s.url).origin);\n } catch {\n /* skip a malformed snippet url rather than breaking the head */\n }\n if (origins.size >= 4) return [...origins];\n }\n }\n return [...origins];\n}\n\nexport function rootHead(ctx: {\n params: Record<string, string>;\n matches?: readonly TwilightContextMatch[];\n}): HeadResult {\n // Re-run on the client during hydration, where the twilight module store may\n // still be empty. Recover it from the resolved match context so the head is\n // built from real settings instead of falling through to 'Store Unavailable'.\n ensureTwilightContextFromMatches(ctx.matches);\n\n let settings: StoreContext | undefined;\n try {\n settings = getTwilightContext().settings;\n } catch (e) {\n if (e instanceof SettingsError) {\n return resolveHead({\n title: 'Store Unavailable',\n });\n }\n throw e;\n }\n const locale = ctx.params.locale || FALLBACK_LOCALE;\n const parts = deriveHeadParts(settings);\n\n return resolveHead(\n mergeHead(buildBaseHead(settings, locale), {\n meta: buildRootMeta(parts),\n links: buildRootLinks(parts),\n styles: buildRootStyles(parts),\n importMap: [{ imports: LIT_IMPORTS }],\n scripts: buildRootScripts(parts),\n })\n );\n}\n\n/** Everything the root head's tag builders read, derived once from the store settings. */\ninterface RootHeadParts {\n store: StoreContext['store'] | undefined;\n favicon?: string;\n primaryColor?: string;\n fontUrl?: string;\n fontUrlWithDisplay?: string;\n isGoogleFont?: boolean;\n fontFamilyName?: string;\n customJs?: string;\n customCss?: string;\n isCustomCssUrl?: boolean;\n isCustomJsUrl?: boolean;\n twilightSdkUrl: string;\n snippetPreconnects: Array<{ rel: 'preconnect'; href: string }>;\n appScopeInstallScript: string;\n themeHookSlotsScript: string | null;\n runtimeEnvScript: string | null;\n}\n\n/** Google Fonts only honours `display=swap` as a query param; other hosts get the @font-face\n * override instead (see buildRootStyles). */\nfunction deriveFontParts(theme?: StoreContext['theme']) {\n const font = theme?.font;\n const fontUrl = font?.url || font?.path;\n const isGoogleFont = fontUrl?.includes('fonts.googleapis.com');\n const needsDisplay = Boolean(isGoogleFont && fontUrl && !fontUrl.includes('display='));\n const separator = fontUrl?.includes('?') ? '&' : '?';\n\n return {\n fontUrl,\n isGoogleFont,\n fontFamilyName: font?.family_name,\n fontUrlWithDisplay: needsDisplay ? `${fontUrl}${separator}display=swap` : fontUrl,\n };\n}\n\n/** Theme customization JS/CSS, each either a URL to load or an inline blob to embed. */\nfunction deriveCustomizationParts(theme?: StoreContext['theme']) {\n const customization = theme?.customization;\n const customJs = customization?.js?.trim();\n const customCss = customization?.css?.trim();\n const isUrl = (value?: string): boolean =>\n Boolean(value?.startsWith('http') || value?.startsWith('//'));\n\n return {\n customJs,\n customCss,\n isCustomCssUrl: isUrl(customCss),\n isCustomJsUrl: isUrl(customJs),\n };\n}\n\nfunction deriveHeadParts(settings?: StoreContext): RootHeadParts {\n const store = settings?.store;\n\n return {\n store,\n favicon: store?.icon,\n primaryColor: settings?.theme?.color?.primary,\n ...deriveFontParts(settings?.theme),\n ...deriveCustomizationParts(settings?.theme),\n twilightSdkUrl: resolveTwilightSdkUrl(settings),\n // Warm the connection to the snippet host(s) during head parse, so the body's deferred\n // `<script src>` snippet tags fetch off an already-open socket instead of DNS+TCP+TLS.\n snippetPreconnects: snippetPreconnectOrigins(getTwilightContext().appsSnippets).map((href) => ({\n rel: 'preconnect' as const,\n href,\n })),\n // Install `Salla.appScope` inline at parse time, before the SDK is ready — else a snippet's\n // onReady callback calls it too early and throws. Always emitted, even when the settings\n // prefetch failed: the CDN snippet tags ship regardless (they come from the *snippets*\n // endpoint), so the factory has to exist for them. `installAppScope` then seeds the real\n // buckets into this install once the client query resolves.\n appScopeInstallScript: renderAppScopeInstallScript(\n getTwilightContext().appsSettings ?? { apps: {} }\n ),\n // Whitelist the theme's own hook slots at parse time too, for the same reason: apps register\n // their `onReady` callbacks from parser-inserted snippet tags, long before React hydrates.\n themeHookSlotsScript: renderThemeHookSlotsScript(),\n // Env this render resolved (worker `vars` live in server-only `process.env`), handed to the\n // client so it doesn't silently fall back to the production defaults. Re-rendered on the\n // client during hydration, where it resolves to the same values or to nothing.\n runtimeEnvScript: renderRuntimeEnvScript(),\n };\n}\n\nfunction buildRootMeta(p: RootHeadParts): NonNullable<HeadDescriptor['meta']> {\n return [\n { name: 'robots', content: 'index, follow' },\n { name: 'msapplication-TileColor', content: '#ffffff' },\n ...(p.favicon ? [{ name: 'msapplication-TileImage', content: p.favicon }] : []),\n ...(p.primaryColor\n ? [\n { name: 'theme-color', content: p.primaryColor },\n { name: 'msapplication-navbutton-color', content: p.primaryColor },\n { name: 'apple-mobile-web-app-status-bar-style', content: p.primaryColor },\n ]\n : []),\n ];\n}\n\nfunction buildRootLinks(p: RootHeadParts): NonNullable<HeadDescriptor['links']> {\n return [\n { rel: 'preconnect', href: 'https://api.salla.dev' },\n { rel: 'preconnect', href: 'https://cdn.salla.sa' },\n { rel: 'preconnect', href: 'https://cdn.assets.salla.network', crossOrigin: 'anonymous' },\n // Warm the installed apps' CDN snippet host(s) — see snippetPreconnectOrigins.\n ...p.snippetPreconnects,\n ...(p.fontUrl\n ? [\n {\n rel: 'preconnect' as const,\n href: 'https://fonts.gstatic.com',\n crossOrigin: 'anonymous' as const,\n },\n ]\n : []),\n { rel: 'modulepreload', href: p.twilightSdkUrl },\n { rel: 'modulepreload', href: `${LIT_CDN_BASE}/lit.js` },\n ...(p.fontUrlWithDisplay\n ? [\n {\n id: 'salla-theme-font',\n rel: 'stylesheet',\n href: p.fontUrlWithDisplay,\n media: 'print',\n },\n ]\n : []),\n ...(p.fontUrlWithDisplay && !p.isGoogleFont && p.fontFamilyName\n ? [\n {\n id: 'salla-font-display-override',\n rel: 'preload',\n as: 'style',\n href: p.fontUrlWithDisplay,\n },\n ]\n : []),\n ...(p.favicon ? [{ rel: 'icon', href: p.favicon }] : []),\n ...(p.favicon\n ? [{ id: 'salla-apple-icon', rel: 'apple-touch-icon-precomposed', href: p.favicon }]\n : []),\n ...(p.isCustomCssUrl && p.customCss\n ? [{ id: 'salla-custom-css', rel: 'stylesheet', href: p.customCss }]\n : []),\n {\n id: 'salla-icons-css',\n rel: 'stylesheet',\n href: SALLA_ICONS_CSS_URL,\n media: 'print',\n },\n // {\n // id: 'intl-tel-input-css',\n // rel: 'stylesheet',\n // href: 'https://cdn.jsdelivr.net/npm/intl-tel-input@26.8.0/build/css/intlTelInput.css',\n // },\n ...(p.isCustomJsUrl && p.customJs\n ? [{ id: 'salla-custom-js-preload', rel: 'preload', as: 'script', href: p.customJs }]\n : []),\n ];\n}\n\nfunction buildRootStyles(p: RootHeadParts): NonNullable<HeadDescriptor['styles']> {\n return [\n { id: 'twilight-loading', children: LOADING_CSS },\n ...(!p.isGoogleFont && p.fontFamilyName\n ? [\n {\n id: 'salla-font-display-swap',\n children: `@font-face{font-family:\"${p.fontFamilyName}\";font-display:swap;src:local(\"${p.fontFamilyName}\")}`,\n },\n ]\n : []),\n ...(!p.isCustomCssUrl && p.customCss\n ? [{ id: 'salla-custom-css', children: p.customCss }]\n : []),\n ];\n}\n\nfunction buildRootScripts(p: RootHeadParts): NonNullable<HeadDescriptor['scripts']> {\n return [\n // First: the API base / store identifier this render used, so the hydrated client\n // resolves the same ones (worker `vars` never reach the browser bundle on their own).\n ...(p.runtimeEnvScript ? [{ id: 'salla-runtime-env', children: p.runtimeEnvScript }] : []),\n { id: 'twilight-init', children: SALLA_INIT_SCRIPT },\n // After twilight-init (which defines window.Salla) and before the SDK module, so the\n // appScope factory exists ahead of any snippet's onReady callback firing.\n { id: 'salla-app-scope', children: p.appScopeInstallScript },\n // Arms the hook-slot whitelist push here, so its `twilight::initiated` listener is\n // registered before any app snippet's — listeners fire in registration order.\n ...(p.themeHookSlotsScript\n ? [{ id: 'salla-theme-hook-slots', children: p.themeHookSlotsScript }]\n : []),\n { id: 'salla-async-css', children: MEDIA_SWAP_SCRIPT },\n { id: 'salla-sdk', type: 'module', src: p.twilightSdkUrl },\n ...(p.store?.settings?.ticketing_system_enabled\n ? [\n {\n id: 'salla-ticketing-script',\n src: 'https://cdn.assets.salla.network/latest/@salla.sa/ui-store-ticketing-system/ticketing-system.es.js',\n type: 'module',\n },\n ]\n : []),\n ...(p.customJs ? [buildCustomJsScript(p.customJs, Boolean(p.isCustomJsUrl))] : []),\n ];\n}\n\n/** A URL customization is loaded after SDK init; an inline one is wrapped so a syntax/runtime\n * error in partner JS warns instead of taking the page down. */\nfunction buildCustomJsScript(customJs: string, isUrl: boolean) {\n return {\n id: 'salla-custom-js',\n children: isUrl\n ? `document.addEventListener('twilight::initiated',function(){var s=document.createElement('script');s.src=${escapeForInlineScript(JSON.stringify(customJs))};s.async=true;document.head.appendChild(s)},{once:true});`\n : `try { ${customJs} } catch(e) { console.warn(\"[ThemeCustomization] Custom JS error:\", e); }`,\n };\n}\n","/**\n * @fileoverview The store segment, carried by the router instead of the route tree.\n *\n * TanStack Router rewrites every location it reads and every one it writes:\n * `input` runs before a URL is matched, and `output` before an href is rendered,\n * pushed to history or sent as a redirect's `Location`. So on a host where the\n * store is the root, the route tree stays `/{-$locale}/cart` and\n * `<Link to=\"/cart\">` renders `/mtgr-alaatr-2/cart` by itself.\n *\n * Why not the router's `basepath`: TanStack Start overwrites it from the build on\n * both sides (`router.update({ basepath })` per request on the server, and in\n * `hydrateStart` on the client). `rewrite` is a separate option that the router\n * composes with that basepath, so it survives. Server functions are dispatched on\n * the raw URL before the router runs, and assets are root-absolute, so neither\n * moves. See `docs/store-base-path.md`.\n */\nimport type { LocationRewrite } from '@tanstack/react-router';\nimport { prefixStoreBase, stripStoreBase } from '../utils/store-base';\n\n/** A rewrite that serves the application from `/<base>`. */\nexport function storeBaseRewrite(base: string): LocationRewrite {\n return {\n input: ({ url }) => {\n url.pathname = stripStoreBase(url.pathname, base);\n return url;\n },\n output: ({ url }) => {\n url.pathname = prefixStoreBase(url.pathname, base);\n return url;\n },\n };\n}\n","import type { ReactNode } from 'react';\nimport { lazy, Suspense } from 'react';\nimport {\n createRouter as createTanStackRouter,\n createRootRouteWithContext,\n} from '@tanstack/react-router';\nimport type { RouterHistory } from '@tanstack/react-router';\nimport { QueryClient } from '@tanstack/react-query';\nimport { shouldDehydrateQuery } from '../api/product';\nimport { PageSkeleton } from '@salla.sa/twilight-components-react/skeletons';\nimport { setHeadAdapter } from '../utils/head';\nimport { tanstackHeadAdapter } from './head';\nimport { updateTwilightContext, type TwilightLocation } from '../twilight/context';\nimport { dispatchRouteChanged } from '../utils/sdk-events';\nimport { rootBeforeLoad, type BeforeLoadResult } from '../routes/root/beforeLoad';\nimport { rootHead } from '../routes/root/head';\nimport { setupRouterSsrQueryIntegration } from '@tanstack/react-router-ssr-query';\nimport type { AnyRouter } from '@tanstack/react-router';\nimport { RouteId, type RouteIdType } from '../router/route-ids';\nimport { UnauthorizedError, NotFoundError, RedirectError } from '../providers/NavigationProvider';\nimport { ErrorPage } from '../components/common/ErrorPage';\nimport type { StoreContext } from '../api/store';\nimport type { AppSnippet, AppSettings } from '../api/apps';\nimport { createI18nInstance } from '../providers/i18n-factory';\nimport { messagesForLocale } from '../api/messages';\nimport { resolveStoreBase } from '../utils/store-identity';\nimport { storeBaseRewrite } from './store-base';\n\n/**\n * Initial router context passed from createRouter to beforeLoad.\n */\nexport interface RouterInitialContext {\n queryClient: QueryClient;\n setLocation: (_location: Partial<TwilightLocation>) => void;\n}\n\n/**\n * TanStack Router ID Mapping\n *\n * Maps TanStack's auto-generated path-based route IDs to semantic RouteId constants.\n * This mapping is TanStack-specific because different frameworks generate route IDs differently:\n *\n * - TanStack: Uses file path as ID (e.g., '/{-$locale}/cart')\n * - Next.js: Uses file path without locale (e.g., '/cart')\n *\n * The mapping enables hooks like useIsHome(), useIsProduct() to work consistently\n * across frameworks while each framework has its own ID generation strategy.\n */\nexport const TANSTACK_ROUTE_ID_MAP: Record<string, RouteIdType> = {\n '/{-$locale}/': RouteId.INDEX,\n '/{-$locale}/cart': RouteId.CART,\n '/{-$locale}/search': RouteId.SEARCH,\n\n '/{-$locale}/latest-products': RouteId.PRODUCT_INDEX_LATEST,\n '/{-$locale}/most-sales-products': RouteId.PRODUCT_INDEX_SALES,\n '/{-$locale}/offers': RouteId.PRODUCT_INDEX_OFFERS,\n\n '/{-$locale}/$slug/c{$id}': RouteId.PRODUCT_INDEX,\n '/{-$locale}/$slug/p{$id}': RouteId.PRODUCT_SINGLE,\n '/{-$locale}/$slug/brand-{$id}': RouteId.BRANDS_SINGLE,\n '/{-$locale}/$slug/tag-{$id}': RouteId.PRODUCT_INDEX_TAG,\n '/{-$locale}/$slug/page-{$id}': RouteId.PAGE_SINGLE,\n\n '/{-$locale}/blog': RouteId.BLOG_INDEX,\n '/{-$locale}/blog/$slug/a-{$id}': RouteId.BLOG_SINGLE,\n '/{-$locale}/blog/$slug/c-{$id}': RouteId.BLOG_INDEX_CATEGORY,\n '/{-$locale}/blog/$slug/tag-{$id}': RouteId.BLOG_INDEX_TAG,\n '/{-$locale}/blog/author/$id': RouteId.BLOG_INDEX_AUTHOR,\n\n '/{-$locale}/brands': RouteId.BRANDS_INDEX,\n '/{-$locale}/brands/$id': RouteId.BRANDS_SINGLE,\n '/{-$locale}/tags/$id': RouteId.PRODUCT_INDEX_TAG,\n\n '/{-$locale}/profile': RouteId.CUSTOMER_PROFILE,\n '/{-$locale}/wishlist': RouteId.CUSTOMER_WISHLIST,\n '/{-$locale}/wallet': RouteId.CUSTOMER_WALLET,\n '/{-$locale}/notifications': RouteId.CUSTOMER_NOTIFICATIONS,\n '/{-$locale}/settings': RouteId.CUSTOMER_SETTINGS,\n '/{-$locale}/orders': RouteId.CUSTOMER_ORDERS_INDEX,\n '/{-$locale}/order/$id': RouteId.CUSTOMER_ORDERS_SINGLE,\n '/{-$locale}/pending-orders': RouteId.CUSTOMER_ORDERS_INDEX_PENDING,\n '/{-$locale}/account/pending_orders': RouteId.CUSTOMER_ORDERS_INDEX_PENDING,\n\n '/{-$locale}/logout': RouteId.LOGOUT,\n '/{-$locale}/loyalty': RouteId.LOYALTY,\n '/{-$locale}/testimonials': RouteId.TESTIMONIALS,\n '/{-$locale}/thankyou/$orderId': RouteId.THANK_YOU,\n};\n\n/**\n * Resolves a TanStack route ID to a semantic RouteId constant.\n * Falls back to the original ID if no mapping exists.\n * @internal Exported for testing\n */\nexport function resolveRouteId(tanstackId: string): string {\n return TANSTACK_ROUTE_ID_MAP[tanstackId] ?? tanstackId;\n}\n\n// Lazy load NotFoundPage for code splitting\nconst LazyNotFoundPage = lazy(() =>\n import('../routes/not-found').then((m) => ({ default: m.NotFoundPage }))\n);\n\n/**\n * Error component shown when the root route fails to load.\n * This renders a minimal HTML page with error details.\n */\nfunction StoreUnavailablePage() {\n return (\n <>\n <div\n style={{\n position: 'fixed',\n inset: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: '#f9fafb',\n }}\n >\n <div style={{ textAlign: 'center', padding: '2rem' }}>\n <h1 style={{ fontSize: '1.5rem', marginBottom: '0.5rem' }}>\n Store is temporarily unavailable\n </h1>\n <p style={{ color: '#6b7280' }}>\n We're having trouble loading the store. Please try again in a moment.\n </p>\n <button\n type=\"button\"\n onClick={() => window.location.reload()}\n style={{\n marginTop: '1rem',\n padding: '0.75rem 1.5rem',\n fontSize: '1rem',\n border: 'none',\n borderRadius: '0.5rem',\n background: '#111827',\n color: '#fff',\n cursor: 'pointer',\n }}\n >\n Retry\n </button>\n </div>\n </div>\n </>\n );\n}\n\nfunction RootErrorComponent({ error: _error }: { error: Error }) {\n return (\n <html lang=\"ar\" dir=\"rtl\">\n <head>\n <meta charSet=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>Store Unavailable</title>\n </head>\n <body style={{ margin: 0, fontFamily: 'sans-serif' }}>\n <StoreUnavailablePage />\n </body>\n </html>\n );\n}\n\n/**\n * Creates the root route pre-configured with RouterInitialContext.\n * beforeLoad will fetch settings/translations, loader returns serializable data.\n *\n * @example\n * ```ts\n * export const Route = createTwilightRootRoute()({ shellComponent });\n * ```\n */\nexport function createTwilightRootRoute() {\n const factory = createRootRouteWithContext<RouterInitialContext>();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TanStack Router factory expects `any` for spread options\n return (options: any) =>\n factory({\n beforeLoad: rootBeforeLoad,\n head: rootHead,\n errorComponent: RootErrorComponent,\n ...options,\n });\n}\n\n/**\n * Default error component for route-level errors.\n */\nexport function DefaultErrorComponent({ error }: { error: unknown }) {\n if (error instanceof RedirectError) {\n return null;\n }\n\n if (error instanceof NotFoundError) {\n return <ErrorPage code={404} message={error.message} />;\n }\n\n if (error instanceof UnauthorizedError) {\n return <ErrorPage code={401} message={error.message} showAction={false} />;\n }\n\n const message =\n error instanceof Error\n ? error.message\n : error &&\n typeof error === 'object' &&\n 'message' in error &&\n typeof error.message === 'string'\n ? error.message\n : undefined;\n\n if (error && typeof error === 'object' && 'response' in error) {\n return <ErrorPage code={400} message={message} />;\n }\n\n return <ErrorPage code={500} message={message} />;\n}\n\n/**\n * SSR integration for Twilight context — mirrors TanStack Query's\n * `setupRouterSsrQueryIntegration` pattern.\n *\n * On the **server**: wraps `router.options.dehydrate` to include twilight\n * context data (settings, locale, location, authToken) alongside the router state.\n *\n * On the **client**: wraps `router.options.hydrate` to populate the module-level\n * store from the root match's `__beforeLoadContext` BEFORE head functions re-run.\n * TanStack's `hydrate()` calls `router.options.hydrate()` at line 114 of\n * `ssr-client.ts`, right before it re-evaluates head functions (line 120+).\n * By populating the store here, `getTwilightContext().settings` is available\n * to `rootHead()` and all child head functions during client hydration.\n */\nfunction setupTwilightSsrIntegration(router: AnyRouter, queryClient: QueryClient): void {\n if (typeof window === 'undefined') {\n // Server: also populate twilightCtx from root match context on dehydrate\n return;\n }\n\n // Client: hook into router.options.hydrate to populate the module store\n // from the root match's __beforeLoadContext (set by rootBeforeLoad on the server)\n const ogHydrate = router.options.hydrate;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n router.options.hydrate = async (dehydratedData: any) => {\n await ogHydrate?.(dehydratedData);\n hydrateTwilightContext(router, queryClient);\n };\n}\n\nfunction warnHydrationBail(reason: string): void {\n // Silent failure here is what blanks the storefront: every head function that\n // runs next reads `getTwilightContext().settings`, which throws when the store\n // is empty. `ensureTwilightContextFromMatches` recovers at the point of use,\n // but the bail still signals a regression worth seeing in dev.\n if (import.meta.env?.DEV) {\n console.warn(`[Twilight] Could not hydrate twilight context: ${reason}`);\n }\n}\n\nfunction hydrateTwilightContext(router: AnyRouter, queryClient: QueryClient): void {\n const rootMatch = router.state?.matches?.[0];\n if (!rootMatch) {\n warnHydrationBail('no root match in router state');\n return;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const beforeLoadCtx = (rootMatch as any).__beforeLoadContext as BeforeLoadResult | undefined;\n const matchCtx = rootMatch.context as Record<string, unknown> | undefined;\n\n const settings = (beforeLoadCtx?.settings ?? matchCtx?.settings) as StoreContext | undefined;\n const locale = (beforeLoadCtx?.locale ?? matchCtx?.locale) as string | undefined;\n const authToken = (beforeLoadCtx?.authToken ?? matchCtx?.authToken) as string | null;\n // Recover snippets here too: this is the primary hydration pass and populates settings, so the\n // best-effort ensureTwilightContextFromMatches fallback then short-circuits — if we skipped\n // appsSnippets here it would never reach the client store, and AppsSnippets' SSR-rendered CDN\n // tags would mismatch on hydration.\n const appsSnippets =\n beforeLoadCtx?.appsSnippets ?? (matchCtx?.appsSnippets as AppSnippet[] | undefined);\n // Recover appScope buckets too (like appsSnippets): this primary pass populates settings, so the\n // ensure-context fallback short-circuits — keep the client store in parity for head/install.\n const appsSettings =\n beforeLoadCtx?.appsSettings ?? (matchCtx?.appsSettings as AppSettings | undefined);\n\n if (!settings || !locale) {\n warnHydrationBail(\n `root match carried no ${!settings ? 'settings' : 'locale'} (beforeLoadContext and context both empty)`\n );\n return;\n }\n\n // Composed by the shared helper rather than read straight off one key.\n // There are two entries now — the platform's copy and this merchant's — and\n // reading only the first is how the server rendered the merchant's wording\n // and hydration replaced it with Salla's (Greptile's P1 on #366).\n const i18n = createI18nInstance(locale, messagesForLocale(queryClient, locale));\n\n const location = router.state?.location\n ? {\n href: router.state.location.href,\n pathname: router.state.location.pathname,\n search: router.state.location.search as Record<string, unknown>,\n searchStr: router.state.location.searchStr,\n state: router.state.location.state as unknown as Record<string, unknown>,\n hash: router.state.location.hash,\n }\n : undefined;\n\n const matches = router.state?.matches;\n const page = matches?.reduceRight(\n (found, m) => found ?? ((m as any).loaderData?.page ? (m as any).loaderData.page : null),\n null as any\n );\n\n // Resolve routeId on the initial load too — `onResolved` only fires on later\n // navigations, so without this the store keeps the empty default until the\n // first SPA navigation (breaks useRouteId/useIsHome on first paint/refresh).\n const leafMatch = matches?.[matches.length - 1];\n const routeId = leafMatch?.routeId ? resolveRouteId(leafMatch.routeId as string) : undefined;\n\n updateTwilightContext({\n queryClient,\n settings,\n locale,\n i18n,\n authToken,\n location,\n page,\n routeId,\n appsSnippets,\n appsSettings,\n });\n}\n\n/**\n * Options for creating the TanStack Router instance.\n */\nexport interface CreateRouterOptions {\n defaultPendingComponent?: (() => ReactNode) | false;\n defaultPendingMs?: number;\n defaultPendingMinMs?: number;\n defaultStaleTime?: number;\n history?: RouterHistory;\n}\n\n/**\n * Creates and configures the TanStack Router instance for the Twilight theme.\n *\n * This router is pre-configured with:\n * - Route tree generated by the TanStack Router plugin\n * - Intent-based preload for better performance\n * - Scroll restoration for better UX\n * - Locale-aware default NotFoundPage (redirects `/cart` → `/ar/cart`)\n * - Trailing slash normalization for consistent URL handling\n * - Page skeleton shown during route transitions (via `defaultPendingComponent`)\n * - SSR query integration for Cloudflare compatibility\n *\n * @param routeTree - The generated route tree from the consuming project\n * @param options - Optional overrides for pending component behavior\n * @returns Configured TanStack Router instance\n */\nexport function createRouter(routeTree: any, options?: CreateRouterOptions) {\n setHeadAdapter(tanstackHeadAdapter);\n\n const {\n defaultPendingComponent: pendingOpt,\n defaultPendingMs = 100,\n defaultPendingMinMs = 200,\n defaultStaleTime = Infinity,\n history,\n } = options ?? {};\n\n const pendingComponent =\n pendingOpt === false ? undefined : (pendingOpt ?? (() => <PageSkeleton />));\n\n const queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: 60_000,\n gcTime: 5 * 60_000,\n retry: 1,\n refetchOnWindowFocus: false,\n },\n mutations: {\n retry: 0,\n },\n dehydrate: {\n shouldDehydrateQuery,\n },\n },\n });\n\n // Store queryClient in the holder for access by loaders via getTwilightContext()\n updateTwilightContext({ queryClient });\n\n // On a host that serves many stores, the store is the first segment of every\n // URL. The router carries it instead of the route tree: it is stripped before\n // matching and added to every href the router builds. Decided per request on\n // the server, and taken from what SSR published in the browser.\n const storeBase = resolveStoreBase();\n\n const router = createTanStackRouter({\n routeTree,\n ...(history ? { history } : {}),\n ...(storeBase ? { rewrite: storeBaseRewrite(storeBase) } : {}),\n context: {\n queryClient,\n setLocation: (location: Partial<TwilightLocation>) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n updateTwilightContext({ location } as any);\n },\n },\n defaultPreload: 'intent',\n scrollRestoration: true,\n scrollRestorationBehavior: 'instant',\n trailingSlash: 'never',\n defaultStaleTime,\n defaultNotFoundComponent: () => (\n <Suspense fallback={<PageSkeleton />}>\n <LazyNotFoundPage />\n </Suspense>\n ),\n defaultPendingComponent: pendingComponent,\n defaultPendingMs,\n defaultPendingMinMs,\n defaultErrorComponent: DefaultErrorComponent,\n });\n\n // Setup SSR query integration (native, with incremental streaming)\n setupRouterSsrQueryIntegration({ router, queryClient });\n\n // Setup Twilight SSR integration — populates the module store from\n // dehydrated match context BEFORE head functions re-run on the client.\n // This mirrors how setupRouterSsrQueryIntegration hydrates QueryClient.\n setupTwilightSsrIntegration(router, queryClient);\n\n // Subscribe to navigation events to sync location and routeId\n function syncNavigationState() {\n const state = router?.state;\n if (!state?.location) return;\n\n const loc = state.location;\n updateTwilightContext({\n location: {\n href: loc.href,\n pathname: loc.pathname,\n search: loc.search as Record<string, unknown>,\n searchStr: loc.searchStr,\n state: loc.state as unknown as Record<string, unknown>,\n hash: loc.hash,\n },\n });\n\n const matches = state.matches;\n const leafMatch = matches[matches.length - 1];\n if (leafMatch?.routeId) {\n const semanticId = resolveRouteId(leafMatch.routeId as string);\n updateTwilightContext({ routeId: semanticId });\n }\n\n const rootMatch = state.matches[0];\n if (rootMatch?.context) {\n const ctx = rootMatch.context as BeforeLoadResult;\n if (ctx?.settings) {\n updateTwilightContext({ settings: ctx.settings, locale: ctx.locale });\n }\n }\n }\n\n // Extract page from matches as soon as loaders complete (before components mount),\n // so useTwilightInit's useEffect sees page data when it calls sdk.init().\n router.subscribe('onLoad', () => {\n const matches = router.state?.matches;\n if (!matches) return;\n const page = matches.reduceRight(\n (found, m) => found ?? ((m as any).loaderData?.page ? (m as any).loaderData.page : null),\n null as any\n );\n if (page) {\n updateTwilightContext({ page });\n // Set page config for SDK\n const salla = window.salla;\n salla?.config?.set?.('page', {\n ...page,\n url: page.url ?? router.state.location.pathname + router.state.location.searchStr,\n });\n }\n });\n\n // Sync location, routeId, and settings after navigation fully resolves\n router.subscribe('onResolved', () => {\n syncNavigationState();\n dispatchRouteChanged();\n });\n\n return router;\n}\n\ndeclare module '@tanstack/react-router' {\n interface Register {\n router: ReturnType<typeof createRouter>;\n }\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type -- Required by TanStack Router module augmentation pattern\n interface RouterContext extends RouterInitialContext {}\n}\n","import { useRouterState } from '@tanstack/react-router';\nimport {\n mergeElementAttrs,\n toReactProps,\n type DocumentElementDescriptor,\n} from '../utils/document-class';\nimport { useDocumentClass } from '../hooks/useDocumentClass';\nimport { updateTwilightContext } from '../twilight/context';\nimport { resolveRouteId } from './router';\n\n// ============================================================================\n// Route → body class map (mirrors PHP Route2Class::generateClassString)\n// Keyed by TanStack Router route ID (the path passed to createFileRoute).\n// null = intentionally classless (e.g. root layout routes).\n// ============================================================================\n\nconst ROUTE_CLASS_MAP: Record<string, string | null> = {\n '/{-$locale}/': 'index',\n '/{-$locale}/cart': 'cart',\n '/{-$locale}/$slug/c{$id}': 'product-index',\n '/{-$locale}/offers': 'product-index-offers',\n '/{-$locale}/latest-products': 'product-index-latest',\n '/{-$locale}/most-sales-products': 'product-index-sales',\n '/{-$locale}/search': 'product-index-search',\n '/{-$locale}/$slug/tag-{$id}': 'product-index-tag',\n '/{-$locale}/tags/$id': 'product-index-tag',\n '/{-$locale}/$slug/p{$id}': 'product-single',\n '/{-$locale}/$slug/page-{$id}': 'page-single',\n '/{-$locale}/page/$slug': 'page-single',\n '/{-$locale}/p/$slug': 'page-single',\n '/{-$locale}/thankyou/$orderId': 'thank-you',\n '/{-$locale}/orders': 'customer-orders-index',\n '/{-$locale}/pending-orders': 'customer-orders-index-pending', // redirect to /account/orders?status=pending\n '/{-$locale}/account/pending_orders': 'customer-orders-index-pending',\n '/{-$locale}/order/$id': 'customer-orders-single',\n '/{-$locale}/profile': 'customer-profile',\n '/{-$locale}/wallet': 'customer-wallet',\n '/{-$locale}/wishlist': 'customer-wishlist',\n '/{-$locale}/notifications': 'customer-notifications',\n '/{-$locale}/testimonials': 'testimonials',\n '/{-$locale}/brands': 'brands-index',\n '/{-$locale}/brands/$id': 'brands-single',\n '/{-$locale}/$slug/brand-{$id}': 'brands-single',\n '/{-$locale}/blog': 'blog-index',\n '/{-$locale}/blog/$slug/a-{$id}': 'blog-single',\n '/{-$locale}/blog/$slug/c-{$id}': 'blog-index-category',\n '/{-$locale}/blog/$slug/tag-{$id}': 'blog-index-tag',\n '/{-$locale}/blog/author/$id': 'blog-index-author',\n '/{-$locale}/loyalty': 'loyalty',\n};\n\n// ============================================================================\n// RouteDocumentSync — resolves body class from active route ID at runtime.\n// ============================================================================\n\n/**\n * Applies the per-route body class by looking up the deepest active route ID\n * in the built-in route→class map.\n *\n * For custom routes not in the built-in map, use `useDocumentClass` directly\n * inside your route component.\n *\n * Note: This will throw if rendered outside a TanStack Router context.\n * Use TanStackDocumentSync for safe usage inside TwilightProvider.\n */\nexport function RouteDocumentSync(): null {\n const matches = useRouterState({ select: (s) => s.matches });\n\n let routeClass: string | null = null;\n for (let i = matches.length - 1; i >= 0; i--) {\n const id = matches[i].routeId;\n if (id in ROUTE_CLASS_MAP) {\n routeClass = ROUTE_CLASS_MAP[id];\n break;\n }\n }\n\n useDocumentClass(routeClass ? { body: { class: routeClass } } : {});\n return null;\n}\n\n/**\n * Safe version of RouteDocumentSync for use in TwilightProvider.\n * Handles being rendered outside a TanStack Router context gracefully.\n * Uses a wrapper component pattern to conditionally render hooks.\n */\nexport function TanStackDocumentSync(): null {\n const matches = useRouterState({ select: (s) => s.matches }) || [];\n\n // On the server routeId is never synced (onResolved is client-only), so useIsHome()\n // etc. disagree with the client and cause hydration mismatches. Sync it here — this\n // renders before the layout. Client already has it from onResolved.\n if (typeof window === 'undefined') {\n const leaf = matches[matches.length - 1];\n if (leaf?.routeId) {\n updateTwilightContext({ routeId: resolveRouteId(leaf.routeId as string) });\n }\n }\n\n let routeClass: string | null = null;\n for (let i = matches.length - 1; i >= 0; i--) {\n const id = matches[i].routeId;\n if (id in ROUTE_CLASS_MAP) {\n routeClass = ROUTE_CLASS_MAP[id];\n break;\n }\n }\n\n useDocumentClass(routeClass ? { body: { class: routeClass } } : {});\n return null;\n}\n\n// ============================================================================\n// Type augmentation — extend TanStack Router's staticData type\n// ============================================================================\n\ndeclare module '@tanstack/react-router' {\n interface StaticDataRouteOption {\n documentAttrs?: DocumentElementDescriptor;\n }\n}\n\nexport interface TanstackRouteStaticData {\n documentAttrs?: DocumentElementDescriptor;\n}\n\n// ============================================================================\n// useTanstackDocumentAttrs — for TanStack Start SSR root layouts\n// ============================================================================\n\n/**\n * Read and merge `<body>` / `<html>` attributes from all currently active\n * route matches (via `staticData.documentAttrs`).\n *\n * Returns React-ready prop objects ready to spread onto `<html>` and `<body>`.\n */\nexport function useTanstackDocumentAttrs(): {\n bodyAttrs: Record<string, string>;\n htmlAttrs: Record<string, string>;\n} {\n const matches = useRouterState({ select: (s) => s.matches });\n\n const bodyDescriptors = matches.map(\n (m) => (m.staticData as TanstackRouteStaticData | undefined)?.documentAttrs?.body ?? {}\n );\n const htmlDescriptors = matches.map(\n (m) => (m.staticData as TanstackRouteStaticData | undefined)?.documentAttrs?.html ?? {}\n );\n\n return {\n bodyAttrs: toReactProps(mergeElementAttrs(bodyDescriptors)),\n htmlAttrs: toReactProps(mergeElementAttrs(htmlDescriptors)),\n };\n}\n\n/**\n * Pure adapter: converts a `DocumentElementDescriptor` to React-ready props.\n */\nexport function tanstackDocumentAdapter(descriptor: DocumentElementDescriptor): {\n bodyAttrs: Record<string, string>;\n htmlAttrs: Record<string, string>;\n} {\n return {\n bodyAttrs: toReactProps(mergeElementAttrs([descriptor.body ?? {}])),\n htmlAttrs: toReactProps(mergeElementAttrs([descriptor.html ?? {}])),\n };\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/providers/NavigationProvider.ts"],"names":[],"mappings":"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","file":"chunk-RLSYCDI4.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';\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\n/** Default redirect - throws RedirectError with browser navigation as fallback */\nexport const defaultRedirect = (path: string, opts?: { replace?: boolean }): 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\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 let notFound = defaultNotFound;\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 let unauthorized = defaultUnauthorized;\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 let redirect = defaultRedirect;\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?: { replace?: boolean }) => never;\n unauthorized?: (_message?: string) => never;\n}): void {\n if (config.notFound) notFound = config.notFound;\n if (config.redirect) redirect = config.redirect;\n if (config.unauthorized) 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 any error, logs debug info and throws notFound() for clean UX.\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 throw new NotFoundError();\n }\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 * 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// ─── 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) return false;\n\n const relativePath = resolveRelativePath(href, currentStoreUrl, usernameRef.current);\n if (!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 if (!anchor || !shouldIntercept(anchor, event)) return;\n\n if (tryNavigate(anchor.href, false)) {\n event.preventDefault();\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 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/routes/account/orders/loader.ts","../src/routes/account/orders/index.tsx"],"names":[],"mappings":"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","file":"chunk-UQAUDOI7.js","sourcesContent":["import { order } from '../../../api/order';\nimport { getTwilightContext } from '../../../twilight/context';\nimport { RouteId } from '../../../router/route-ids';\nimport { orUnauthorized } from '../../../providers/NavigationProvider';\nimport type { OrdersPageProps, OrderSinglePageProps, OrdersQuery } from './types';\nimport type { IdParams } from '../../types';\n\nexport async function ordersLoader(\n ctx: { query?: OrdersQuery; with_items?: boolean | number },\n extend?: (\n data: OrdersPageProps,\n ctx: { params: Record<string, never> }\n ) => Promise<Record<string, unknown>> | Record<string, unknown>\n): Promise<OrdersPageProps> {\n const query = ctx.query;\n const isPending = query?.status === 'pending';\n const response = await orUnauthorized(\n order.list({\n status: query?.status,\n feedback_status: query?.feedback_status,\n ...(ctx.with_items ? { with_items: ctx.with_items } : {}),\n })\n );\n const i18n = getTwilightContext().i18n;\n const pageData: OrdersPageProps = {\n page: {\n title: isPending\n ? i18n.t('common.titles.pending_orders') || 'Pending Orders'\n : i18n.t('common.titles.orders') || 'Orders',\n slug: 'orders',\n },\n orders: response.data,\n cursor: response.cursor,\n query,\n };\n\n if (extend) {\n const extra = await extend(pageData, { params: {} });\n return { ...pageData, ...extra } as OrdersPageProps;\n }\n return pageData;\n}\n\nexport async function orderSingleLoader({\n params,\n}: {\n params: IdParams;\n}): Promise<OrderSinglePageProps> {\n const data = await order.findOrThrow(params.id);\n const i18n = getTwilightContext().i18n;\n return {\n page: {\n slug: RouteId.CUSTOMER_ORDERS_SINGLE,\n id: String(params.id),\n title: (i18n.t('pages.orders.order_details') || 'Order Details').replace(':id', params.id),\n },\n order: data.order,\n };\n}\n","import type { HeadDescriptor } from '../../../utils/head';\nimport { buildHreflangAlternates } from '../../../utils/baseHead';\nimport { lazy } from 'react';\nimport { ordersLoader, orderSingleLoader } from './loader';\nimport type { OrdersPageProps, OrderSinglePageProps, OrdersSearchParams } from './types';\nimport type { IdParams } from '../../types';\nimport type { TwilightContext } from '../../../twilight/context';\nimport { RouteId } from '../../../router/route-ids';\n\n// Lazy-load components for code-splitting\nconst LazyOrdersPage = lazy(() => import('./OrdersPage').then((m) => ({ default: m.OrdersPage })));\nconst LazyOrderSinglePage = lazy(() =>\n import('./OrderSinglePage').then((m) => ({ default: m.OrderSinglePage }))\n);\n\nexport const OrdersPage = LazyOrdersPage;\nexport const OrderSinglePage = LazyOrderSinglePage;\nexport { ordersLoader, orderSingleLoader } from './loader';\nexport type {\n OrdersPageProps,\n OrderSinglePageProps,\n OrdersSearchParams,\n OrdersQuery,\n} from './types';\n\nasync function ordersLoaderWithExtend(\n ctx: { search?: OrdersSearchParams; locale?: string; with_items?: boolean | number },\n extend?: (\n data: OrdersPageProps,\n ctx: { params: Record<string, never> }\n ) => Promise<Record<string, unknown>> | Record<string, unknown>\n): Promise<OrdersPageProps> {\n const query = ctx.search;\n const data = await ordersLoader({ query, with_items: ctx.with_items }, extend);\n\n if (extend) {\n const extra = await extend(data, { params: {} });\n return { ...data, ...extra } as OrdersPageProps;\n }\n return data;\n}\n\nfunction ordersHead(ctx: TwilightContext, data: OrdersPageProps): HeadDescriptor {\n const isPending = ctx.location.search?.status === 'pending';\n const base: HeadDescriptor = {\n title: ctx.i18n.t(isPending ? 'common.titles.pending_orders' : 'common.titles.orders'),\n description: data.page.description,\n alternateLanguages: buildHreflangAlternates(ctx.settings, ctx.location.pathname),\n };\n\n return base;\n}\n\nasync function orderSingleLoaderWithExtend(\n ctx: { params: IdParams; locale?: string },\n extend?: (\n data: OrderSinglePageProps,\n ctx: { params: IdParams }\n ) => Promise<Record<string, unknown>> | Record<string, unknown>\n): Promise<OrderSinglePageProps> {\n const data = await orderSingleLoader({ params: ctx.params });\n\n if (extend) {\n const extra = await extend(data, ctx);\n return { ...data, ...extra } as OrderSinglePageProps;\n }\n return data;\n}\n\nfunction orderSingleHead(ctx: TwilightContext, data: OrderSinglePageProps): HeadDescriptor {\n const base: HeadDescriptor = {\n title: data.page.title,\n description: data.page.description,\n alternateLanguages: buildHreflangAlternates(ctx.settings, ctx.location.pathname),\n };\n\n return base;\n}\n\nexport const Orders = {\n id: RouteId.CUSTOMER_ORDERS_INDEX,\n loader: ordersLoaderWithExtend,\n head: ordersHead,\n Component: LazyOrdersPage,\n} as const;\nexport const OrderSingle = {\n id: RouteId.CUSTOMER_ORDERS_SINGLE,\n loader: orderSingleLoaderWithExtend,\n head: orderSingleHead,\n Component: LazyOrderSinglePage,\n} as const;\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/inline-script.ts","../src/utils/runtime-env.ts","../src/utils/store-identity.ts","../src/utils/sdk-helpers.ts"],"names":[],"mappings":";;;;AAMO,SAAS,sBAAsB,KAAA,EAAuB;AAC3D,EAAA,OAAO,MACJ,OAAA,CAAQ,IAAA,EAAM,SAAS,CAAA,CACvB,OAAA,CAAQ,MAAM,SAAS,CAAA,CACvB,QAAQ,IAAA,EAAM,SAAS,EACvB,OAAA,CAAQ,SAAA,EAAW,SAAS,CAAA,CAC5B,OAAA,CAAQ,WAAW,SAAS,CAAA;AACjC;;;ACRA,IAAM,eAAA,GAAkB,uBAAA;AAsCjB,SAAS,QAAQ,GAAA,EAAiC;AACvD,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAQ,MAAA,CAAA,IAAA,CAAwE,GAAA,GACpF,GACF,CAAA;AACA,IAAA,IAAI,MAAM,OAAO,IAAA;AAAA,EACnB,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,OAAO,OAAO,OAAA,KAAY,WAAA,GAAc,OAAA,CAAQ,GAAA,GAAM,GAAG,CAAA,GAAI,MAAA;AAC/D;AAOO,SAAS,iBAAA,GAAgC;AAC9C,EAAA,MAAM,WAAW,qBAAA,EAAsB;AACvC,EAAA,MAAM,EAAE,OAAA,EAAS,SAAA,EAAW,SAAA,EAAW,WAAA,KAAgB,eAAA,EAAgB;AACvE,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,QAAA,CAAS,OAAA,IAAW,OAAA,CAAQ,cAAc,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMnD,eAAA,EACE,QAAA,CAAS,eAAA,IACT,OAAA,IACA,SAAA,KACC,mBAAA,CAAoB,WAAW,CAAA,GAAI,WAAA,GAAc,IAAA,CAAA,IAClD,OAAA,CAAQ,mBAAmB,CAAA;AAAA;AAAA;AAAA,IAG7B,SAAA,EAAW,QAAA,CAAS,SAAA,IAAa,SAAA,IAAa,MAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAK9C,SAAA,EAAW,QAAA,CAAS,SAAA,IAAa,SAAA,IAAa;AAAA,GAChD;AACF;AAWO,SAAS,qBAAA,GAAoC;AAClD,EAAA,MAAM,MAAA,GAAS,UAAA;AACf,EAAA,OAAO,MAAA,CAAO,eAAe,CAAA,IAAK,EAAC;AACrC;AAMO,SAAS,sBAAA,CAAuB,GAAA,GAAkB,iBAAA,EAAkB,EAAkB;AAC3F,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA,CAAE,MAAA,CAAO,CAAC,GAAG,KAAK,CAAA,KAAM,OAAA,CAAQ,KAAK,CAAC,CAAA;AACpE,EAAA,IAAI,CAAC,GAAA,CAAI,MAAA,EAAQ,OAAO,IAAA;AACxB,EAAA,MAAM,IAAA,GAAO,sBAAsB,IAAA,CAAK,SAAA,CAAU,OAAO,WAAA,CAAY,GAAG,CAAC,CAAC,CAAA;AAC1E,EAAA,OAAO,CAAA,OAAA,EAAU,eAAe,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,CAAA;AAC1C;;;ACtDO,SAAS,uBAAuB,QAAA,EAA2B;AAChE,EAAA,IAAI,UAAU,OAAO,QAAA;AAErB,EAAA,MAAM,EAAE,OAAA,EAAS,WAAA,EAAY,GAAI,eAAA,EAAgB;AACjD,EAAA,IAAI,SAAS,OAAO,OAAA;AAEpB,EAAA,MAAM,YAAY,gBAAA,EAAiB;AACnC,EAAA,IAAI,WAAW,OAAO,SAAA;AAEtB,EAAA,MAAM,QAAA,GAAW,uBAAsB,CAAE,eAAA;AACzC,EAAA,IAAI,UAAU,OAAO,QAAA;AAErB,EAAA,IAAI,mBAAA,CAAoB,WAAW,CAAA,EAAG,OAAO,WAAA;AAI7C,EAAA,MAAM,cAAc,OAAO,MAAA,KAAW,WAAA,GAAc,MAAA,CAAO,SAAS,IAAA,GAAO,IAAA;AAC3E,EAAA,IAAI,mBAAA,CAAoB,WAAW,CAAA,EAAG,OAAO,WAAA;AAE7C,EAAA,OAAO,OAAA,CAAQ,mBAAmB,CAAA,IAAK,OAAA,CAAQ,cAAc,CAAA,IAAK,EAAA;AACpE;AAkBO,SAAS,gBAAA,GAAkC;AAChD,EAAA,MAAM,EAAE,SAAA,EAAU,GAAI,eAAA,EAAgB;AACtC,EAAA,IAAI,WAAW,OAAO,SAAA;AACtB,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,EAAa,OAAO,IAAA;AAE1C,EAAA,MAAM,YAAY,qBAAA,EAAsB;AACxC,EAAA,IAAI,SAAA,CAAU,SAAA,EAAW,OAAO,SAAA,CAAU,SAAA;AAC1C,EAAA,IAAI,OAAO,IAAA,CAAK,SAAS,CAAA,CAAE,MAAA,GAAS,GAAG,OAAO,IAAA;AAE9C,EAAA,OAAO,wBAAwB,MAAA,CAAO,QAAA,CAAS,IAAA,EAAM,MAAA,CAAO,SAAS,IAAI,CAAA;AAC3E;AAaO,SAAS,wBAAA,CACd,UACA,IAAA,EACe;AACf,EAAA,MAAM,IAAA,GACJ,iBAAgB,CAAE,WAAA,KAAgB,OAAO,MAAA,KAAW,WAAA,GAAc,MAAA,CAAO,QAAA,CAAS,IAAA,GAAO,IAAA,CAAA;AAC3F,EAAA,OAAO,qBAAA,CAAsB,EAAE,IAAA,EAAM,IAAA,EAAM,kBAAiB,EAAG,QAAA,EAAU,MAAM,CAAA;AACjF;;;ACzHA,IAAM,SAAA,GAAY,OAAO,MAAA,KAAW,WAAA;AAc7B,SAAS,mBAAmB,QAAA,EAA2B;AAC5D,EAAA,OAAO,uBAAuB,QAAQ,CAAA;AACxC;AAKO,SAAS,WAAA,GAA+C;AAC7D,EAAA,IAAI,CAAC,WAAW,OAAO,MAAA;AACvB,EAAA,OAAO,MAAA,CAAO,KAAA;AAChB;AAoBO,SAAS,cAAc,MAAA,EAAsB;AAClD,EAAA,MAAM,MAAM,WAAA,EAAY;AACxB,EAAA,IAAI,CAAC,GAAA,IAAO,CAAC,MAAA,EAAQ;AACrB,EAAA,IAAI;AACF,IAAA,GAAA,CAAI,IAAA,EAAM,YAAY,MAAM,CAAA;AAC5B,IAAA,GAAA,CAAI,GAAA,EAAK,SAAA,GAAY,iBAAA,EAAmB,MAAM,CAAA;AAG9C,IAAA,GAAA,CAAI,MAAA,EAAQ,GAAA,GAAM,oBAAA,EAAsB,MAAM,CAAA;AAAA,EAChD,CAAA,CAAA,MAAQ;AAAA,EAER;AACF","file":"chunk-VRV5F6G7.js","sourcesContent":["/**\n * Escape a JSON-stringified value for safe embedding inside an inline `<script>` body.\n *\n * The head injects script bodies raw, so a `</script>` inside partner-set data would break out\n * of the tag; U+2028/U+2029 are line terminators in JS but not in JSON, so they must go too.\n */\nexport function escapeForInlineScript(value: string): string {\n return value\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/&/g, '\\\\u0026')\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029');\n}\n","import { escapeForInlineScript } from './inline-script';\nimport { getRequestStore } from '../twilight/context';\nimport { hostIdentifiesStore } from './cookies';\n\n/** Where `rootHead` publishes the SSR-resolved env for the browser bundle to read. */\nconst RUNTIME_ENV_KEY = '__SALLA_RUNTIME_ENV__';\n\n/** The env values that must agree between the SSR render and the hydrated client. */\nexport interface RuntimeEnv {\n /** Store API base — `VITE_API_URL`. */\n apiBase?: string;\n /** Store identifier — `VITE_STORE_DOMAIN`. */\n storeIdentifier?: string;\n /**\n * The theme-settings version the request named, if any.\n *\n * Published for the same reason `storeIdentifier` is: the dispatcher strips\n * `?versionId=` on the way in, so by the time the browser has the page its own\n * URL no longer says which version it is showing. Without this the hydrated\n * client would ask the API about the store's live version and quietly replace\n * the draft it was handed.\n *\n * Absent — not empty — when nothing named one, so it drops out of the inline\n * script entirely rather than publishing a value that means \"live\".\n */\n versionId?: string;\n /**\n * The store segment at the root of this page's paths, when the store is\n * addressed that way — see `resolveStoreBase`.\n *\n * Published because the browser's address is not always the URL the server\n * read: the dispatcher removes `?storeId=` from the request it forwards but not\n * from the address bar, and a URL carrying it is never read for a segment. The\n * client builds its router from this, and a router that disagreed with the\n * server about the root would hydrate a different page.\n */\n storeBase?: string;\n}\n\n/**\n * A build-time `import.meta.env` var, falling back to the worker's runtime `process.env`\n * (wrangler `vars`, exposed via the `nodejs_compat_populate_process_env` flag).\n */\nexport function readEnv(key: string): string | undefined {\n try {\n const vite = (import.meta as unknown as { env?: Record<string, string | undefined> }).env?.[\n key\n ];\n if (vite) return vite;\n } catch {\n /* import.meta.env not available in all environments */\n }\n return typeof process !== 'undefined' ? process.env?.[key] : undefined;\n}\n\n/**\n * What this runtime resolves from its own env — server-side that includes the worker vars.\n * Prefers what the server already published, so re-rendering the head during hydration yields\n * the same script instead of dropping it.\n */\nexport function resolveRuntimeEnv(): RuntimeEnv {\n const injected = getInjectedRuntimeEnv();\n const { storeId, storeBase, versionId, requestHost } = getRequestStore();\n return {\n apiBase: injected.apiBase || readEnv('VITE_API_URL'),\n // The request outranks the build-time var here for the same reason it does\n // in `resolveStoreIdentifier`, and this is the copy that reaches the\n // browser: publish the store SSR actually rendered, or hydration resolves\n // again from a URL whose `?storeId=` the dispatcher has already stripped and\n // queries a different store than the markup it is hydrating.\n storeIdentifier:\n injected.storeIdentifier ||\n storeId ||\n storeBase ||\n (hostIdentifiesStore(requestHost) ? requestHost : null) ||\n readEnv('VITE_STORE_DOMAIN'),\n // Absent rather than empty when the path named no store, so it drops out of\n // the inline script, like `versionId`.\n storeBase: injected.storeBase || storeBase || undefined,\n // No env fallback on purpose. A store identifier has one because a build can\n // legitimately be pinned to a store; a version is something a request asks\n // for, and a build-time default would make every visitor of every store see\n // whichever draft was current when the theme was compiled.\n versionId: injected.versionId || versionId || undefined,\n };\n}\n\n/**\n * The env the SSR worker resolved, as handed to the browser by `rootHead`. Empty on the server\n * and on a client whose head carried nothing.\n *\n * Worker `vars` are *runtime* env: they live in `process.env` on the server only, while\n * `import.meta.env` is substituted at build time. A bundle built without those vars therefore\n * sees `undefined` in the browser and silently falls back to the production defaults — SSR\n * would render off the configured backend while every post-hydration fetch hits another one.\n */\nexport function getInjectedRuntimeEnv(): RuntimeEnv {\n const holder = globalThis as typeof globalThis & { [RUNTIME_ENV_KEY]?: RuntimeEnv };\n return holder[RUNTIME_ENV_KEY] ?? {};\n}\n\n/**\n * Inline head `<script>` body publishing the server-resolved env, or null when there is nothing\n * to publish (no overrides configured — the defaults already agree on both sides).\n */\nexport function renderRuntimeEnvScript(env: RuntimeEnv = resolveRuntimeEnv()): string | null {\n const set = Object.entries(env).filter(([, value]) => Boolean(value));\n if (!set.length) return null;\n const json = escapeForInlineScript(JSON.stringify(Object.fromEntries(set)));\n return `window.${RUNTIME_ENV_KEY}=${json};`;\n}\n","/**\n * @fileoverview Which store to ask about — the one answer, in one place.\n *\n * This lived in two places once. `api/store.ts` learned to read the store a\n * request names, and `utils/sdk-helpers.ts` — the copy `api/client.ts` actually\n * sets the `store-identifier` header from — did not. So the resolver that had\n * been taught the answer was consulted for a null check and thrown away, every\n * outgoing request carried an empty identifier, the API answered\n * `422 Store Identifier not found`, and every published theme rendered\n * \"Store Unavailable\" while its tests passed: the client's suite mocked the\n * resolver, and the resolver's suite never went near a request.\n *\n * Hence one module, imported by both. If a third place ever needs a store\n * identifier, it imports this — a second implementation is the bug, not a\n * refactor away from it.\n *\n * See `docs/store-identity.md` for the full picture, including the security\n * boundary on who may name a store.\n */\nimport { getRequestStore } from '../twilight/context';\nimport { hostIdentifiesStore, resolveRequestStoreBase } from './cookies';\nimport { getInjectedRuntimeEnv, readEnv } from './runtime-env';\nimport { storeBaseRedirectHref } from './store-base';\n\n/**\n * Which store to ask about, in the order the answers can be trusted.\n *\n * A deployed theme worker is published with **no vars and no bindings** — the\n * script metadata carries `main_module`, compatibility settings, assets and tags\n * and nothing else — so `VITE_STORE_DOMAIN` exists only where a build baked it\n * in, which is local development. In production this function used to reach the\n * end of that chain and return the empty string, `store.settings` refused to\n * call with no identifier, and the root loader threw \"Store Unavailable\" — a\n * theme that renders its own failure page for every visitor of every store.\n *\n * The order:\n *\n * 1. what the caller passed, which is always deliberate;\n * 2. the store this request names — the `?storeId=` a preview was opened with,\n * then the cookie remembering it — seeded by `twilightMiddleware`, and only\n * on a host permitted to name one;\n * 3. the store the first segment of the path names, on those same hosts — its\n * username, which the API accepts as an identifier as readily as an id (see\n * {@link resolveStoreBase});\n * 4. what SSR already resolved and published, so the hydrated client asks about\n * the same store the server rendered instead of resolving again from a URL\n * that no longer names it;\n * 5. the request's own host, which *is* the identity of a live storefront —\n * but only when that host is a storefront. `preview.salla.design` and\n * `localhost` serve many stores, so their names identify none;\n * 6. `VITE_STORE_DOMAIN`, last, because a build-time constant is a development\n * convenience and must never outrank what the request actually said.\n *\n * Steps 2 and 3 never both answer: a path that names a store takes the place of\n * the cookie, and a URL carrying `?storeId=` is not read for a path segment.\n */\nexport function resolveStoreIdentifier(explicit?: string): string {\n if (explicit) return explicit;\n\n const { storeId, requestHost } = getRequestStore();\n if (storeId) return storeId;\n\n const storeBase = resolveStoreBase();\n if (storeBase) return storeBase;\n\n const injected = getInjectedRuntimeEnv().storeIdentifier;\n if (injected) return injected;\n\n if (hostIdentifiesStore(requestHost)) return requestHost as string;\n\n // The browser's own address, for a client render that reached neither of the\n // above — a live storefront, where the host is the store.\n const browserHost = typeof window !== 'undefined' ? window.location.host : null;\n if (hostIdentifiesStore(browserHost)) return browserHost as string;\n\n return readEnv('VITE_STORE_DOMAIN') || readEnv('STORE_DOMAIN') || '';\n}\n\n/**\n * The store segment at the root of this page's paths, or null when the store is\n * not addressed that way.\n *\n * On the server it is what `twilightMiddleware` read off the request. In the\n * browser it is what SSR published, because the address bar is not always the\n * URL the server rendered: on the preview host the dispatcher removes\n * `?storeId=` from the request it forwards and leaves it in the browser's, and a\n * URL carrying `storeId` is never read for a segment. Re-reading\n * `window.location` would, for `/ar?storeId=…`, route the page under a different\n * store than the one it was rendered for.\n *\n * The address bar is read only when SSR published nothing at all: a page the dev\n * server answered with its client shell instead of a render, where there is no\n * server decision to agree with.\n */\nexport function resolveStoreBase(): string | null {\n const { storeBase } = getRequestStore();\n if (storeBase) return storeBase;\n if (typeof window === 'undefined') return null;\n\n const published = getInjectedRuntimeEnv();\n if (published.storeBase) return published.storeBase;\n if (Object.keys(published).length > 0) return null;\n\n return resolveRequestStoreBase(window.location.href, window.location.host);\n}\n\n/**\n * The address this page should be loaded from instead, when the store is the root\n * of every URL on this host and this request did not use it; null otherwise.\n *\n * @param username - the store's username, from the settings the request loaded\n * @param href - the router's own href for the page, without any store segment\n *\n * See `storeBaseRedirectHref` for the rules. The host is the request's on the\n * server and the browser's own in the browser, so the decision is gated the same\n * way on both sides.\n */\nexport function resolveStoreBaseRedirect(\n username: string | null | undefined,\n href: string\n): string | null {\n const host =\n getRequestStore().requestHost ?? (typeof window !== 'undefined' ? window.location.host : null);\n return storeBaseRedirectHref({ host, base: resolveStoreBase(), username, href });\n}\n","export type { StoreContext } from '../api/store';\nimport { resolveStoreIdentifier } from './store-identity';\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/**\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"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/cookies.ts","../src/utils/store-base.ts"],"names":[],"mappings":"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","file":"chunk-XTMHHLNK.js","sourcesContent":["import { isLocale } from '../providers/locale-constants';\n\nexport const AUTH_TOKEN_COOKIE_NAME = 'token';\nexport const SCOPE_COOKIE_NAME = 'scope';\n\n/**\n * Which store this request is for, when the hostname does not say.\n *\n * A live storefront is reached at its own domain, so the hostname identifies it\n * and nothing else is needed. A preview is not: every theme under review is\n * served from the one preview hostname, so the store has to be named some other\n * way — the dispatcher takes it from `?storeId=` and puts it here, the same way\n * it remembers which theme to serve.\n *\n * Written by the dispatcher rather than the theme, and set on the *forwarded\n * request* as well as the response, because the response cookie only arrives in\n * time for the second page load and the first one has to render too.\n *\n * The literal is a contract with `STORE_COOKIE` in store-front-dispacher\n * (`src/dispatch/preview.ts`), and **nothing checks the two agree**. Drift does\n * not fail loudly — it renders somebody else's shop. Grep both repos before\n * changing it.\n */\nexport const STORE_ID_COOKIE_NAME = 'salla_sid';\n\n/** Query parameter naming the store, on a host that serves more than one. */\nexport const STORE_ID_PARAM = 'storeId';\n\n/**\n * Which version of the theme's settings to render.\n *\n * A merchant's theme settings are versioned, and the storefront normally shows\n * whichever version is live — the API answers with it, and names it back as\n * `theme.profile.id`. Two places need a different one: the merchant's own theme\n * editor, which previews a draft version before it is published, and a partner\n * running a theme locally against a store whose settings they are editing. Both\n * open the theme inside an iframe, and the version travels in that URL.\n *\n * Named `versionId` rather than the `version_id` the Dashboard uses internally,\n * because it sits beside `?storeId=` and one URL should not spell two ids two\n * ways. The value is the same one either way: the Optimus-encoded version id,\n * which is exactly what `s-version-id` has always carried.\n *\n * The literal is a contract with `VERSION_COOKIE` in store-front-dispacher\n * (`src/dispatch/preview.ts`), on the same terms as {@link STORE_ID_COOKIE_NAME}:\n * nothing checks the two agree, and drift shows a merchant the wrong version of\n * their own settings rather than failing.\n */\nexport const VERSION_ID_COOKIE_NAME = 'salla_vid';\n\n/** Query parameter naming the theme-settings version, where one may be named. */\nexport const VERSION_ID_PARAM = 'versionId';\n\n/**\n * An id named by a request is an integer, and anything else is not one.\n *\n * Validated rather than passed through because these values end up in an upstream\n * API path and header. Leading zeroes, signs, decimals and whitespace are all\n * rejected: the point is a single canonical form, not the widest set of things\n * that could be coerced into a number.\n *\n * One function for both ids on purpose. They arrive the same way, from the same\n * untrusted place, and are spent the same way; two copies of this rule would be\n * two chances for one of them to be relaxed on its own.\n */\nfunction parseRequestId(raw: string | null | undefined): string | null {\n if (!raw) return null;\n return /^[1-9][0-9]{0,18}$/.test(raw) ? raw : null;\n}\n\n/** A store id in its canonical form, or null when it is not one. */\nexport function parseStoreId(raw: string | null | undefined): string | null {\n return parseRequestId(raw);\n}\n\n/** A theme-settings version id in its canonical form, or null when it is not one. */\nexport function parseVersionId(raw: string | null | undefined): string | null {\n return parseRequestId(raw);\n}\n\n/** The store id the dispatcher left in the cookie, or null when absent or malformed. */\nexport function extractStoreIdFromCookies(cookieHeader: string | null): string | null {\n return parseStoreId(extractTokenFromCookies(cookieHeader, STORE_ID_COOKIE_NAME));\n}\n\n/** The version id the dispatcher left in the cookie, or null when absent or malformed. */\nexport function extractVersionIdFromCookies(cookieHeader: string | null): string | null {\n return parseVersionId(extractTokenFromCookies(cookieHeader, VERSION_ID_COOKIE_NAME));\n}\n\n/**\n * The only hosts on which a request may name its own store.\n *\n * **This is a security boundary, not a convenience.** On a merchant's own domain\n * the hostname *is* the store, and it is the only thing that may decide. A theme\n * that also honoured `?storeId=` there would let anyone open\n * `https://reefperfumes.com/?storeId=<someone else>` and be served a different\n * merchant's shop from the domain its owner controls — their branding, their\n * customers' address bar, somebody else's catalogue — and the cookie would keep\n * serving it for the rest of that browser's session. Salla points SaaS domains\n * at this dispatcher, so those hostnames are real and reachable.\n *\n * The override exists for one situation: a host that serves many stores and so\n * cannot identify one from its name. That is the preview host, where every theme\n * under review answers on the same address, and local development.\n *\n * Adding an entry grants that host the ability to render any store on request.\n * Add nothing that a merchant's traffic reaches.\n */\nexport const STORE_ID_HOSTS: readonly string[] = ['preview.salla.design'];\n\n/** The hostname alone — a port never distinguishes one host's authority from another's. */\nfunction hostnameOf(host: string): string {\n const trimmed = host.trim().toLowerCase();\n // IPv6 literals are bracketed, and the colons inside them are not a port.\n if (trimmed.startsWith('[')) return trimmed.slice(0, trimmed.indexOf(']') + 1) || trimmed;\n const colon = trimmed.indexOf(':');\n return colon === -1 ? trimmed : trimmed.slice(0, colon);\n}\n\nfunction isLoopback(hostname: string): boolean {\n return (\n hostname === 'localhost' ||\n hostname === '127.0.0.1' ||\n hostname === '[::1]' ||\n hostname.endsWith('.localhost')\n );\n}\n\n/**\n * Whether this host is allowed to let the request choose a store.\n *\n * Deliberately an allowlist of exact hostnames plus loopback. No suffix matching:\n * a rule like \"anything ending in salla.design\" is one wildcard DNS record away\n * from admitting a host nobody meant to admit, and the list of hosts that serve\n * more than one store is short and known.\n *\n * It gates {@link resolveRequestVersionId} as well, and the name has been left\n * alone rather than generalised because one predicate that both call is the\n * property worth keeping — a second, subtly different list is how a host ends up\n * permitted to name one thing and not the other. A version is worth gating for\n * the same reason a store is: on a merchant's own domain, honouring\n * `?versionId=` would publish whatever draft settings they are still working on\n * to anyone who guessed the URL.\n */\nexport function allowsRequestStoreId(host: string | null | undefined): boolean {\n if (!host) return false;\n const hostname = hostnameOf(host);\n return STORE_ID_HOSTS.includes(hostname) || isLoopback(hostname);\n}\n\n/**\n * Whether this host *is* a store, so its name can be used as the identifier.\n *\n * The exact inverse of {@link allowsRequestStoreId}, and deliberately written as\n * one so the two can never disagree: a host that may name its store is a host\n * that serves more than one, and a host that serves more than one cannot be the\n * answer to \"which store is this?\". `preview.salla.design` and `localhost:5188`\n * are not shops; asking the API about them earns a 422 and a page that reads as\n * a broken theme.\n */\nexport function hostIdentifiesStore(host: string | null | undefined): boolean {\n return Boolean(host) && !allowsRequestStoreId(host);\n}\n\n/**\n * The store this request names, on a host permitted to name one.\n *\n * The host check is inside the resolution rather than at a call site, because a\n * call site is a thing someone can add without reading this comment. There is no\n * way to ask \"what store did the request name?\" without also asking \"is this a\n * host that may say?\" — get it wrong and the answer is a security bug that looks\n * like a feature.\n *\n * Between the two permitted sources the URL wins, the same precedence the\n * dispatcher uses for the theme and for the same reason: a link is how someone\n * switches, and a cookie they cannot see should never beat the address they\n * just typed.\n */\nexport function resolveRequestStoreId(\n url: string,\n cookieHeader: string | null,\n host: string | null | undefined\n): string | null {\n return resolveRequestId(url, cookieHeader, host, STORE_ID_PARAM, STORE_ID_COOKIE_NAME);\n}\n\n/**\n * A store username as it can appear as the first segment of a path.\n *\n * Starts with a letter or digit, so nothing the platform mounts at the root of a\n * host — `/_serverFn/`, `/.well-known/`, `/favicon.ico` — is ever read as a store.\n * The value is sent upstream as the `store-identifier` header, so the set is kept\n * narrow on purpose: a username outside it cannot be addressed by path, and\n * `?storeId=` still can.\n */\nconst STORE_BASE_SEGMENT = /^[a-z0-9][a-z0-9_-]{0,62}$/i;\n\n/**\n * Whether this could be a store's username in the first segment of a path.\n *\n * A supported locale code never is, in any case: `/ar` and `/EN` are languages,\n * so `preview.salla.design/en/cart` is the English cart of the store the cookie\n * names. That makes a store whose username is a locale code (`ar` is one)\n * unreachable by path; `?storeId=` still reaches it.\n *\n * The same predicate decides whether a username may become a path's root\n * (`storeBaseRedirectHref`). That is what stops the redirect from looping: a\n * store called `ar`, sent to `/ar/…`, would find no store there and be sent again.\n */\nexport function isStoreBaseSegment(value: string | null | undefined): value is string {\n return (\n typeof value === 'string' && STORE_BASE_SEGMENT.test(value) && !isLocale(value.toLowerCase())\n );\n}\n\n/**\n * The store the first segment of this request's path names, on a host permitted\n * to name one.\n *\n * On such a host the first segment **is** the store. It is the root of the\n * application there, so `https://preview.salla.design/mtgr-alaatr-2/cart` is the\n * cart of the store whose username is `mtgr-alaatr-2`. This is a rule rather than\n * a guess, and it has to be: `cart`, `offers` and `search` are all real store\n * usernames, so a store cannot be told from a page by looking at the segment.\n * `/cart` on these hosts is the store called `cart`.\n *\n * The one segment that is not a store is a supported locale code (see\n * {@link isStoreBaseSegment}). `/ar/cart` names a language, and the store comes\n * from the cookie or `VITE_STORE_DOMAIN`, as it would at `/`.\n *\n * A URL that carries `storeId` is not read this way at all, whatever its value.\n * That is how `salla theme dev` names a store (`/ar?storeId=…`), on a path that\n * begins with a page; the root loader then redirects to the store's own address.\n * Checking for a *valid* id instead would let a malformed one hand the page's\n * first segment the store's job. (On the preview host the dispatcher removes the\n * parameter and sends a cookie; the editor opens that host at `/`, where there is\n * no segment to read.)\n *\n * Same gate as {@link resolveRequestStoreId}, for the same reason: on a merchant's\n * own domain the hostname is the store and the path is only ever a page.\n */\nexport function resolveRequestStoreBase(\n url: string,\n host: string | null | undefined\n): string | null {\n if (!allowsRequestStoreId(host)) return null;\n\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return null;\n }\n if (parsed.searchParams.has(STORE_ID_PARAM)) return null;\n\n const first = parsed.pathname.split('/')[1];\n return isStoreBaseSegment(first) ? first : null;\n}\n\n/** Which store a request addressed, and how. At most one of the two is set. */\nexport interface RequestStore {\n /** Named by `?storeId=`, or by the cookie remembering it. */\n storeId: string | null;\n /** Named by the first segment of the path. */\n storeBase: string | null;\n}\n\n/**\n * The store this request addressed: the query, then the path, then the cookie.\n *\n * The path outranks the cookie because it is the address the visitor can see.\n * The cookie is one value for the whole preview host, so with two stores open in\n * two tabs it names whichever was opened last; the path names the one in front\n * of them.\n */\nexport function resolveRequestStore(\n url: string,\n cookieHeader: string | null,\n host: string | null | undefined\n): RequestStore {\n const storeBase = resolveRequestStoreBase(url, host);\n return {\n storeBase,\n storeId: storeBase ? null : resolveRequestStoreId(url, cookieHeader, host),\n };\n}\n\n/**\n * The theme-settings version this request names, on a host permitted to name one.\n *\n * Same shape and the same host gate as {@link resolveRequestStoreId}, deliberately:\n * both answer \"what did this request ask to be shown?\", both are reached only on\n * a host that serves more than one thing, and a version that could be named where\n * a store could not would be a second rule to keep in step with the first.\n *\n * Null is the ordinary answer, and it is not a failure — it means nothing\n * addressed a version, so the store's own live one is what gets rendered.\n */\nexport function resolveRequestVersionId(\n url: string,\n cookieHeader: string | null,\n host: string | null | undefined\n): string | null {\n return resolveRequestId(url, cookieHeader, host, VERSION_ID_PARAM, VERSION_ID_COOKIE_NAME);\n}\n\n/**\n * The id this request names, from the query first and the cookie after.\n *\n * The host check lives here rather than at either call site, for the reason the\n * two wrappers above are wrappers at all: there must be no way to ask what a\n * request named without also asking whether this host may say.\n */\nfunction resolveRequestId(\n url: string,\n cookieHeader: string | null,\n host: string | null | undefined,\n param: string,\n cookieName: string\n): string | null {\n if (!allowsRequestStoreId(host)) return null;\n\n let fromQuery: string | null = null;\n try {\n fromQuery = parseRequestId(new URL(url).searchParams.get(param));\n } catch {\n /* a relative or malformed URL simply names nothing */\n }\n return fromQuery ?? parseRequestId(extractTokenFromCookies(cookieHeader, cookieName));\n}\n\n/**\n * Deletes the auth `token` cookie. This cookie is written client-side by the theme\n * (TwilightProvider), not by the SDK — `salla.cookie.clearAll()` only clears its own\n * allowlist and leaves `token` behind — so logout must clear it here. Client-only.\n */\nexport function clearAuthTokenCookie(): void {\n if (typeof document === 'undefined') return;\n document.cookie = `${AUTH_TOKEN_COOKIE_NAME}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;\n}\n\nexport function extractTokenFromCookies(\n cookieHeader: string | null,\n cookieName: string\n): string | null {\n if (!cookieHeader) return null;\n\n const prefix = `${cookieName}=`;\n let start = 0;\n\n while (start < cookieHeader.length) {\n const idx = cookieHeader.indexOf(prefix, start);\n if (idx === -1) return null;\n\n const prevChar = idx > 0 ? cookieHeader[idx - 1] : '';\n if (prevChar === '' || prevChar === ';' || prevChar === ' ') {\n let end = cookieHeader.indexOf(';', idx);\n if (end === -1) end = cookieHeader.length;\n\n const value = cookieHeader.slice(idx + prefix.length, end).trim();\n try {\n return decodeURIComponent(value) || null;\n } catch {\n return value || null;\n }\n }\n\n start = idx + prefix.length;\n }\n\n return null;\n}\n\n/**\n * The scope the Salla SDK persists as `scope`: the market (`id`/`type`) plus, once\n * bullet delivery confirms an address or branch, the allocation. The SDK sends all\n * four as request headers (`s-scope-id`, `s-scope-type`, `s-scope-allocation-type`,\n * `s-scope-allocation-id`) and the API resolves stock per allocation — a scope sent\n * without its allocation is a different question, answered from a different branch.\n */\nexport interface ActiveScope {\n id: string;\n type?: string;\n allocation_type?: string;\n allocation_id?: string;\n}\n\n/** The SDK stores the scope either as its full object or as a bare id. */\nfunction normalizeScope(raw: unknown): ActiveScope | null {\n if (raw == null) return null;\n if (typeof raw !== 'object') return { id: String(raw) };\n const s = raw as Record<string, unknown>;\n if (s.id == null) return null;\n const scope: ActiveScope = { id: String(s.id) };\n if (s.type != null) scope.type = String(s.type);\n if (s.allocation_type != null) scope.allocation_type = String(s.allocation_type);\n if (s.allocation_id != null) scope.allocation_id = String(s.allocation_id);\n return scope;\n}\n\n/**\n * Reads the active scope from the `scope` cookie, which Salla persists as a JSON\n * object (e.g. `{\"id\":123,\"type\":\"scope\",\"allocation_type\":\"branch\",\"allocation_id\":\"9\"}`).\n * Returns null when the cookie is missing or unparseable. Used server-side, where\n * `salla.storage` is absent.\n */\nexport function extractScopeFromCookies(cookieHeader: string | null): ActiveScope | null {\n const raw = extractTokenFromCookies(cookieHeader, SCOPE_COOKIE_NAME);\n if (!raw) return null;\n try {\n return normalizeScope(JSON.parse(raw));\n } catch {\n return null;\n }\n}\n\n/** {@link extractScopeFromCookies} reduced to the id. */\nexport function extractScopeIdFromCookies(cookieHeader: string | null): string | null {\n return extractScopeFromCookies(cookieHeader)?.id ?? null;\n}\n\n/**\n * The scope the Salla SDK persisted in its storage (`salla.storage.get('scope')`).\n *\n * Returns `undefined` when the SDK storage API isn't ready yet — deliberately\n * distinct from `null` (\"no branch selected\"), so callers can't mistake a\n * not-yet-hydrated SDK for a cleared selection. Client-only.\n */\nexport function readSdkScope(): ActiveScope | null | undefined {\n const storage = typeof window !== 'undefined' ? window.salla?.storage : undefined;\n if (typeof storage?.get !== 'function') return undefined;\n return normalizeScope(storage.get(SCOPE_COOKIE_NAME));\n}\n\n/** {@link readSdkScope} reduced to the id; keeps the not-ready/none distinction. */\nexport function readSdkScopeId(): string | null | undefined {\n const scope = readSdkScope();\n return scope === undefined ? undefined : (scope?.id ?? null);\n}\n\n/** One year — the SDK keeps the selected branch in localStorage indefinitely. */\nconst SCOPE_COOKIE_MAX_AGE = 60 * 60 * 24 * 365;\n\nconst sameScope = (a: ActiveScope | null, b: ActiveScope | null): boolean =>\n JSON.stringify(a) === JSON.stringify(b);\n\n/**\n * Mirrors the scope the Salla SDK selected into the `scope` cookie so the SERVER\n * can see it. The SDK persists the selection in localStorage ONLY and writes no\n * cookie, so without this the server computes scope=null for every visitor who\n * picked a branch while the client computes the branch id — the dehydrated settings\n * query key never matches and the client refetches store settings on every page\n * load (SAL-122).\n *\n * Written in the SDK's own JSON shape so {@link extractScopeFromCookies} parses it,\n * allocation included: the bullet-delivery component writes the same cookie with the\n * full object, and rewriting it with the id alone would drop the branch the server\n * needs. Returns true when the cookie was (re)written. Client-only; no-op on the server.\n */\nexport function writeScopeCookie(scope: ActiveScope | null): boolean {\n if (typeof document === 'undefined') return false;\n if (sameScope(extractScopeFromCookies(document.cookie), scope)) return false;\n\n if (scope == null) {\n document.cookie = `${SCOPE_COOKIE_NAME}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;\n return true;\n }\n\n const value = encodeURIComponent(JSON.stringify(scope));\n document.cookie = `${SCOPE_COOKIE_NAME}=${value}; path=/; max-age=${SCOPE_COOKIE_MAX_AGE}; samesite=lax`;\n return true;\n}\n\n/**\n * Keeps the `scope` cookie in step with the SDK's selected branch. Call on every\n * client navigation; it no-ops while the SDK storage API is still hydrating so a\n * late-loading SDK can't wipe a valid cookie.\n */\nexport function syncScopeCookie(): boolean {\n const scope = readSdkScope();\n return scope === undefined ? false : writeScopeCookie(scope);\n}\n","/**\n * @fileoverview Paths on a host where the store is the root.\n *\n * On `preview.salla.design` and a dev server a store is addressed by the first\n * segment of the path — `/mtgr-alaatr-2/cart` — and that segment is the root of\n * the application. No route knows about it: the router takes it off every URL on\n * the way in and puts it back on every URL on the way out\n * (`tanstack/store-base.ts`), so pages, links and loaders all see `/cart`.\n *\n * Which segment it is, and on which hosts, is decided once, by\n * `resolveRequestStoreBase` in `utils/cookies.ts`. This file only moves it on and\n * off a path. See `docs/store-base-path.md`.\n */\nimport { allowsRequestStoreId, isStoreBaseSegment, STORE_ID_PARAM } from './cookies';\nimport { isLocale } from '../providers/locale-constants';\n\n/**\n * An application pathname, without the store segment in front.\n *\n * Only a whole segment is removed, so `/mtgr-alaatr-2x/cart` is left alone, and a\n * pathname that does not start with the segment comes back unchanged.\n */\nexport function stripStoreBase(pathname: string, base: string): string {\n const prefix = `/${base}`;\n if (pathname === prefix) return '/';\n return pathname.startsWith(`${prefix}/`) ? pathname.slice(prefix.length) : pathname;\n}\n\n/**\n * An application path as the browser addresses it, with the store segment in front.\n *\n * It never checks whether the segment is already there, because that cannot be\n * told apart from a page of the same name: a store called `cart` keeps its cart at\n * `/cart/cart`. Callers pass application paths only.\n */\nexport function prefixStoreBase(path: string, base: string): string {\n const rooted = path.startsWith('/') ? path : `/${path}`;\n // The store's root is `/<base>`, not `/<base>/`, with or without a query or hash.\n const atRoot = rooted === '/' || rooted[1] === '?' || rooted[1] === '#';\n return `/${base}${atRoot ? rooted.slice(1) : rooted}`;\n}\n\n/**\n * A pathname from a link the Salla API handed out, without the store's username in it.\n *\n * A store with no domain of its own is served under its username on a shared host,\n * and every URL the API returns for it carries that segment. Its `store.url` is\n * `/{lang}/{username}/` when the store is multilingual and `/{username}/` when it is\n * not: `https://demostore.salla.sa/ar/dev-vgckq3fssfhjewwi/`, `https://salla.sa/cart/`.\n * The segment there belongs to Salla's host, not to the application. Left in, it\n * lands where a page slug is expected and matches no route.\n *\n * The username is the last segment of `store.url`, but only when it equals the\n * store's username. Neither its position nor its spelling says so on its own: `/ar/`\n * is the locale of `https://3tir.com/ar/`, a store on its own domain whose links carry\n * no username, and it is also the whole address of the store called `ar`,\n * `https://salla.sa/ar/`. Without a username to compare against, a last segment\n * spelled like a locale is taken to be one, which is wrong only for a store whose\n * username is a locale code.\n *\n * The locale stays wherever the link put it.\n */\nexport function withoutStoreUrlBase(\n pathname: string,\n storeUrlPathname: string,\n username?: string | null\n): string {\n const own = storeUrlSegment(storeUrlPathname, username);\n if (!own) return pathname;\n\n const segments = pathname.split('/');\n // Salla puts the locale first (`/ar/dev-x/…`); a store that is not multilingual has\n // none (`/dev-x/…`). Checked in that order, `/ar/ar/…` for a store called `ar` keeps\n // its locale.\n let at = -1;\n if (isLocale(segments[1]) && segments[2] === own) at = 2;\n else if (segments[1] === own) at = 1;\n if (at === -1) return pathname;\n\n segments.splice(at, 1);\n return segments.join('/') || '/';\n}\n\n/** The segment `store.url` serves the store under, or null when it has none. */\nfunction storeUrlSegment(storeUrlPathname: string, username?: string | null): string | null {\n const last = storeUrlPathname.split('/').filter(Boolean).pop();\n if (!last) return null;\n if (username) return last === username ? last : null;\n return isLocale(last) ? null : last;\n}\n\n/**\n * Where to send a page whose store was not named by its own first segment, or null\n * when it already was.\n *\n * On a host where the store is the root, every page has one address,\n * `/<username>/…`. A request that found its store some other way (`?storeId=`, the\n * preview cookie, `VITE_STORE_DOMAIN`, or a first segment that named the store by\n * another spelling, such as its numeric id) is sent there once the store's settings\n * say what its username is.\n *\n * `storeId` is dropped from the query on the way. It has to be: a URL carrying it\n * is never read for a store segment, so keeping it would redirect to an address\n * that redirects again, forever. For the same reason a username that could not be\n * read back out of a path produces no redirect at all.\n *\n * `href` is the application's own href (path, query and hash, already without any\n * store segment), which the router keeps percent-encoded, so the result is safe to\n * put in a `Location` header.\n */\nexport function storeBaseRedirectHref(args: {\n host: string | null | undefined;\n base: string | null;\n username: string | null | undefined;\n href: string;\n}): string | null {\n const { host, base, username, href } = args;\n if (!allowsRequestStoreId(host) || !isStoreBaseSegment(username) || username === base) {\n return null;\n }\n\n const url = new URL(href, 'http://store-base.invalid');\n url.searchParams.delete(STORE_ID_PARAM);\n return `${prefixStoreBase(url.pathname, username)}${url.search}${url.hash}`;\n}\n"]}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
export { RouteDocumentSync, TanStackDocumentSync, tanstackDocumentAdapter, useTanstackDocumentAttrs } from './chunk-R2ULWW5T.js';
|
|
2
|
-
import './chunk-Z4Y55HWX.js';
|
|
3
|
-
import './chunk-NKLKKZM6.js';
|
|
4
|
-
import './chunk-S7JSNUU2.js';
|
|
5
|
-
import './chunk-B3EFOE57.js';
|
|
6
|
-
import './chunk-GXXWHVLS.js';
|
|
7
|
-
import './chunk-ZOZLNUNA.js';
|
|
8
|
-
import './chunk-TZ3E5BN4.js';
|
|
9
|
-
import './chunk-NK2V2SW5.js';
|
|
10
|
-
import './chunk-X7P2WSNU.js';
|
|
11
|
-
import './chunk-YGDAYFQY.js';
|
|
12
|
-
import './chunk-RLSYCDI4.js';
|
|
13
|
-
import './chunk-TFB3QXYH.js';
|
|
14
|
-
import './chunk-BHU25UEW.js';
|
|
15
|
-
import './chunk-VRV5F6G7.js';
|
|
16
|
-
import './chunk-XTMHHLNK.js';
|
|
17
|
-
import './chunk-OGQXRBCR.js';
|
|
18
|
-
import './chunk-JWXJPJBO.js';
|
|
19
|
-
import './chunk-CW625T2E.js';
|
|
20
|
-
import './chunk-TYNZ5B2B.js';
|
|
21
|
-
import './chunk-T72DAX7R.js';
|
|
22
|
-
import './chunk-DF6FBKDN.js';
|
|
23
|
-
import './chunk-DGUM43GV.js';
|
|
24
|
-
//# sourceMappingURL=document-class-SX2LHILG.js.map
|
|
25
|
-
//# sourceMappingURL=document-class-SX2LHILG.js.map
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export { NavigationSetup, TanStackNavigationProvider } from './chunk-HAV32VZS.js';
|
|
2
|
-
import './chunk-RLSYCDI4.js';
|
|
3
|
-
import './chunk-TFB3QXYH.js';
|
|
4
|
-
import './chunk-XTMHHLNK.js';
|
|
5
|
-
import './chunk-OGQXRBCR.js';
|
|
6
|
-
import './chunk-T72DAX7R.js';
|
|
7
|
-
import './chunk-BYMOPN2S.js';
|
|
8
|
-
import './chunk-DF6FBKDN.js';
|
|
9
|
-
import './chunk-DGUM43GV.js';
|
|
10
|
-
//# sourceMappingURL=navigation-Z6JMJ4FZ.js.map
|
|
11
|
-
//# sourceMappingURL=navigation-Z6JMJ4FZ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/routes/product-short-link.ts","../src/routes/not-found.tsx"],"names":[],"mappings":"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","file":"not-found-CDXSWL7T.js","sourcesContent":["import { useEffect, useState } from 'react';\nimport { product } from '../api/product';\nimport { isLocale } from '../providers/locale-constants';\nimport { useLocation, useNavigate } from '../providers/NavigationProvider';\n\n/** Short codes are 5-10 letters/digits (e.g. `lvXvzln`). */\nconst SHORT_CODE = /^[A-Za-z0-9]{5,10}$/;\n\n/**\n * The product short code in a path shaped `/{locale}/{code}` or `/{code}` (the\n * store base is already stripped from the router's location), plus the locale\n * segment to keep when redirecting. `null` for any other path.\n */\nexport function parseShortLinkPath(pathname: string): { code: string; locale?: string } | null {\n const segments = pathname.split('/').filter(Boolean);\n if (segments.length === 2 && isLocale(segments[0]) && SHORT_CODE.test(segments[1])) {\n return { code: segments[1], locale: segments[0] };\n }\n if (segments.length === 1 && !isLocale(segments[0]) && SHORT_CODE.test(segments[0])) {\n return { code: segments[0] };\n }\n return null;\n}\n\n/** The SEO slug from a product URL (`…/{slug}/p{id}`), `-` when it has none. */\nexport function slugFromProductUrl(url: string | undefined): string {\n try {\n const segments = new URL(url ?? '').pathname.split('/').filter(Boolean);\n const last = segments[segments.length - 1] ?? '';\n return /^p\\d+$/.test(last) && segments.length > 1 ? segments[segments.length - 2] : '-';\n } catch {\n return '-';\n }\n}\n\n/**\n * Resolves a product short link (`/ar/lvXvzln`) that matched no route: the\n * products API accepts the code as an id, so look it up and replace the URL with\n * the product's canonical page. Returns `true` while a lookup is in flight (so the\n * 404 isn't flashed); settles to `false` when the path isn't a short link or the\n * code doesn't resolve.\n */\nexport function useProductShortLink(): boolean {\n const { pathname } = useLocation();\n const navigate = useNavigate();\n const target = parseShortLinkPath(pathname);\n const code = target?.code;\n const locale = target?.locale;\n const [failedCode, setFailedCode] = useState<string | null>(null);\n\n useEffect(() => {\n if (!code) return;\n let cancelled = false;\n product\n .find(code)\n .then((found) => {\n if (cancelled) return;\n if (!found?.id) return setFailedCode(code);\n const prefix = locale ? `/${locale}` : '';\n navigate(`${prefix}/${slugFromProductUrl(found.url)}/p${found.id}`, { replace: true });\n })\n .catch(() => !cancelled && setFailedCode(code));\n return () => {\n cancelled = true;\n };\n }, [code, locale, navigate]);\n\n return !!code && failedCode !== code;\n}\n","import type { ComponentType, ReactNode } from 'react';\nimport { HookSlot } from '../hooks';\nimport { useTranslation } from '../providers/I18nProvider';\nimport { ErrorPage } from '../components/common';\nimport { useProductShortLink } from './product-short-link';\n\nexport interface NotFoundPageProps {\n title?: string;\n message?: string;\n showHomeLink?: boolean;\n homeLinkText?: string;\n LinkComponent?: ComponentType<{\n to: string;\n className?: string;\n style?: React.CSSProperties;\n children: ReactNode;\n }>;\n}\n\nexport function NotFoundPage(props: NotFoundPageProps = {}) {\n const { t } = useTranslation();\n // A product short link (`/ar/lvXvzln`) matches no route; resolve it instead of 404ing.\n const resolvingShortLink = useProductShortLink();\n\n const {\n title = t('common.errors.404') || 'Page Not Found',\n message = t('common.errors.error_occurred') ||\n 'The page you are looking for does not exist or has been moved.',\n showHomeLink = true,\n homeLinkText = t('common.elements.back_home') || 'Back to Home',\n LinkComponent,\n } = props;\n\n if (resolvingShortLink) return null;\n\n return (\n <ErrorPage\n code={404}\n title={title}\n message={message}\n showAction={showHomeLink}\n actionText={homeLinkText}\n LinkComponent={LinkComponent}\n >\n <HookSlot name=\"notfound:start\" />\n <HookSlot name=\"notfound:content\" />\n <HookSlot name=\"notfound:end\" />\n </ErrorPage>\n );\n}\n"]}
|