@salla.sa/twilight-theme-engine 1.0.141 → 1.0.143
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-WNDQP34Y.js → AddToCartForm-HIIF72O4.js} +3 -3
- package/dist/{AddToCartForm-WNDQP34Y.js.map → AddToCartForm-HIIF72O4.js.map} +1 -1
- package/dist/{BlogAuthorPage-U4CFZZWU.js → BlogAuthorPage-LVUTPDWU.js} +16 -16
- package/dist/{BlogAuthorPage-U4CFZZWU.js.map → BlogAuthorPage-LVUTPDWU.js.map} +1 -1
- package/dist/{BlogCategoryPage-JXCHHGMM.js → BlogCategoryPage-4Q2MU5IF.js} +16 -16
- package/dist/{BlogCategoryPage-JXCHHGMM.js.map → BlogCategoryPage-4Q2MU5IF.js.map} +1 -1
- package/dist/{BlogPage-BLSTB5BQ.js → BlogPage-YG3INJ6S.js} +14 -14
- package/dist/{BlogPage-BLSTB5BQ.js.map → BlogPage-YG3INJ6S.js.map} +1 -1
- package/dist/{BlogSinglePage-TUNH4RZZ.js → BlogSinglePage-P4OPKCYA.js} +14 -14
- package/dist/{BlogSinglePage-TUNH4RZZ.js.map → BlogSinglePage-P4OPKCYA.js.map} +1 -1
- package/dist/{BlogTagPage-24P5YHNB.js → BlogTagPage-RC4CSYJM.js} +16 -16
- package/dist/{BlogTagPage-24P5YHNB.js.map → BlogTagPage-RC4CSYJM.js.map} +1 -1
- package/dist/{BrandsPage-2TES2Y7B.js → BrandsPage-SRQANTCQ.js} +15 -15
- package/dist/{BrandsPage-2TES2Y7B.js.map → BrandsPage-SRQANTCQ.js.map} +1 -1
- package/dist/{Breadcrumb-MUN36Q5L.js → Breadcrumb-I6RHU7TL.js} +14 -14
- package/dist/{Breadcrumb-MUN36Q5L.js.map → Breadcrumb-I6RHU7TL.js.map} +1 -1
- package/dist/{CartItem-FM6RUM2U.js → CartItem-WXV4HG7L.js} +14 -14
- package/dist/{CartItem-FM6RUM2U.js.map → CartItem-WXV4HG7L.js.map} +1 -1
- package/dist/{CartSummary-P6PEKCS7.js → CartSummary-66PEAPVR.js} +14 -14
- package/dist/{CartSummary-P6PEKCS7.js.map → CartSummary-66PEAPVR.js.map} +1 -1
- package/dist/{Copyright-EHQHBFRP.js → Copyright-ADNRUD2V.js} +3 -3
- package/dist/{Copyright-EHQHBFRP.js.map → Copyright-ADNRUD2V.js.map} +1 -1
- package/dist/{CustomerLayout-QRBLOWA4.js → CustomerLayout-S4PJGKMT.js} +14 -14
- package/dist/{CustomerLayout-QRBLOWA4.js.map → CustomerLayout-S4PJGKMT.js.map} +1 -1
- package/dist/{Footer-GH6UEQR2.js → Footer-RYWLSTKI.js} +4 -4
- package/dist/{Footer-GH6UEQR2.js.map → Footer-RYWLSTKI.js.map} +1 -1
- package/dist/{Header-4KUXZJMA.js → Header-IM7KKNSG.js} +8 -8
- package/dist/{Header-4KUXZJMA.js.map → Header-IM7KKNSG.js.map} +1 -1
- package/dist/{LatestProducts-AKCLYRRU.js → LatestProducts-VMDICC67.js} +16 -16
- package/dist/{LatestProducts-AKCLYRRU.js.map → LatestProducts-VMDICC67.js.map} +1 -1
- package/dist/{LoyaltyPage-MUMMZ37S.js → LoyaltyPage-N7LLJ3ZW.js} +14 -14
- package/dist/{LoyaltyPage-MUMMZ37S.js.map → LoyaltyPage-N7LLJ3ZW.js.map} +1 -1
- package/dist/{LoyaltyPointsPage-N6XMXNZY.js → LoyaltyPointsPage-HVK6PJRL.js} +6 -6
- package/dist/{LoyaltyPointsPage-N6XMXNZY.js.map → LoyaltyPointsPage-HVK6PJRL.js.map} +1 -1
- package/dist/{MainMenu-Q5R3HK7F.js → MainMenu-ICQUOKYN.js} +5 -5
- package/dist/{MainMenu-Q5R3HK7F.js.map → MainMenu-ICQUOKYN.js.map} +1 -1
- package/dist/{MasterLayout-3VXL2VCQ.js → MasterLayout-WO743UZA.js} +14 -14
- package/dist/{MasterLayout-3VXL2VCQ.js.map → MasterLayout-WO743UZA.js.map} +1 -1
- package/dist/{MobileMenu-UY3GHY7B.js → MobileMenu-TK5S3UAR.js} +15 -15
- package/dist/{MobileMenu-UY3GHY7B.js.map → MobileMenu-TK5S3UAR.js.map} +1 -1
- package/dist/{NotificationsPage-N3MF2RS7.js → NotificationsPage-FNC7EOFV.js} +14 -14
- package/dist/{NotificationsPage-N3MF2RS7.js.map → NotificationsPage-FNC7EOFV.js.map} +1 -1
- package/dist/{OrderSinglePage-3XHUQGEW.js → OrderSinglePage-YS6FBSCD.js} +38 -21
- package/dist/OrderSinglePage-YS6FBSCD.js.map +1 -0
- package/dist/{OrdersPage-SWBRRHAH.js → OrdersPage-V3YMXMSN.js} +14 -14
- package/dist/{OrdersPage-SWBRRHAH.js.map → OrdersPage-V3YMXMSN.js.map} +1 -1
- package/dist/{PageSingle-YZCWWOAW.js → PageSingle-QAAJ6NL7.js} +3 -3
- package/dist/{PageSingle-YZCWWOAW.js.map → PageSingle-QAAJ6NL7.js.map} +1 -1
- package/dist/{ProductDetails-V27IGZYV.js → ProductDetails-DUQPPDWZ.js} +4 -4
- package/dist/{ProductDetails-V27IGZYV.js.map → ProductDetails-DUQPPDWZ.js.map} +1 -1
- package/dist/{ProfilePage-57TZ4ZKP.js → ProfilePage-L7DOZZBH.js} +14 -14
- package/dist/{ProfilePage-57TZ4ZKP.js.map → ProfilePage-L7DOZZBH.js.map} +1 -1
- package/dist/{ReviewsPage-JC2ZKARA.js → ReviewsPage-6EIMUR5L.js} +3 -3
- package/dist/{ReviewsPage-JC2ZKARA.js.map → ReviewsPage-6EIMUR5L.js.map} +1 -1
- package/dist/{SeoCartWidget-D3GIOO56.js → SeoCartWidget-IW2EIOP3.js} +14 -14
- package/dist/{SeoCartWidget-D3GIOO56.js.map → SeoCartWidget-IW2EIOP3.js.map} +1 -1
- package/dist/{SettingsPage-C2PSTHXQ.js → SettingsPage-3BZD6EXX.js} +14 -14
- package/dist/{SettingsPage-C2PSTHXQ.js.map → SettingsPage-3BZD6EXX.js.map} +1 -1
- package/dist/{StoreClosedNotification-NXDQW24E.js → StoreClosedNotification-Z7QF4CPA.js} +15 -15
- package/dist/{StoreClosedNotification-NXDQW24E.js.map → StoreClosedNotification-Z7QF4CPA.js.map} +1 -1
- package/dist/{TestimonialsPage-MENUPYFS.js → TestimonialsPage-IA7YUNJI.js} +3 -3
- package/dist/{TestimonialsPage-MENUPYFS.js.map → TestimonialsPage-IA7YUNJI.js.map} +1 -1
- package/dist/{ThankYouPage-WNX3JNVJ.js → ThankYouPage-GPPMDT4G.js} +14 -14
- package/dist/{ThankYouPage-WNX3JNVJ.js.map → ThankYouPage-GPPMDT4G.js.map} +1 -1
- package/dist/{WalletPage-FKIRJ327.js → WalletPage-JYNPVXER.js} +15 -15
- package/dist/{WalletPage-FKIRJ327.js.map → WalletPage-JYNPVXER.js.map} +1 -1
- package/dist/{WishlistPage-5LOWSXHY.js → WishlistPage-APID33BZ.js} +16 -16
- package/dist/{WishlistPage-5LOWSXHY.js.map → WishlistPage-APID33BZ.js.map} +1 -1
- package/dist/api/advertisement.js +2 -2
- package/dist/api/apps.js +2 -2
- package/dist/api/blog.js +3 -3
- package/dist/api/brands.js +3 -3
- package/dist/api/cart.js +3 -3
- package/dist/api/category.js +3 -3
- package/dist/api/client.js +1 -1
- package/dist/api/home.js +2 -2
- package/dist/api/loyalty.js +3 -3
- package/dist/api/menu.js +2 -2
- package/dist/api/notification.js +2 -2
- package/dist/api/order.js +3 -3
- package/dist/api/page.js +3 -3
- package/dist/api/product.js +3 -3
- package/dist/api/profile.js +1 -1
- package/dist/api/store.js +2 -2
- package/dist/api/translations.js +2 -2
- package/dist/api/user.js +2 -2
- package/dist/api/wallet.js +2 -2
- package/dist/api/wishlist.js +4 -4
- package/dist/{chunk-TGPAAFOW.js → chunk-2FISCDW2.js} +4 -4
- package/dist/{chunk-TGPAAFOW.js.map → chunk-2FISCDW2.js.map} +1 -1
- package/dist/{chunk-C7UFIC63.js → chunk-2LB2TBNP.js} +3 -3
- package/dist/{chunk-C7UFIC63.js.map → chunk-2LB2TBNP.js.map} +1 -1
- package/dist/{chunk-CSPVLZDC.js → chunk-2OHGW43N.js} +3 -3
- package/dist/{chunk-CSPVLZDC.js.map → chunk-2OHGW43N.js.map} +1 -1
- package/dist/{chunk-RQY66Y3Z.js → chunk-3MDXVF4Y.js} +5 -5
- package/dist/{chunk-RQY66Y3Z.js.map → chunk-3MDXVF4Y.js.map} +1 -1
- package/dist/{chunk-HK3545K3.js → chunk-42GSY6HV.js} +4 -4
- package/dist/{chunk-HK3545K3.js.map → chunk-42GSY6HV.js.map} +1 -1
- package/dist/{chunk-RISG443X.js → chunk-4LTS5AZ3.js} +3 -3
- package/dist/{chunk-RISG443X.js.map → chunk-4LTS5AZ3.js.map} +1 -1
- package/dist/{chunk-NTOWUMLA.js → chunk-4RKNISJB.js} +3 -3
- package/dist/{chunk-NTOWUMLA.js.map → chunk-4RKNISJB.js.map} +1 -1
- package/dist/{chunk-ENQEMMQ5.js → chunk-4XB425HW.js} +14 -14
- package/dist/{chunk-ENQEMMQ5.js.map → chunk-4XB425HW.js.map} +1 -1
- package/dist/{chunk-W4RC4HES.js → chunk-4XUBBJUJ.js} +10 -10
- package/dist/{chunk-W4RC4HES.js.map → chunk-4XUBBJUJ.js.map} +1 -1
- package/dist/{chunk-ASLBVSLC.js → chunk-7BNWZKXI.js} +4 -4
- package/dist/{chunk-ASLBVSLC.js.map → chunk-7BNWZKXI.js.map} +1 -1
- package/dist/{chunk-DD622QIQ.js → chunk-7HZ6JQAJ.js} +3 -3
- package/dist/{chunk-DD622QIQ.js.map → chunk-7HZ6JQAJ.js.map} +1 -1
- package/dist/{chunk-EVBRWESV.js → chunk-ATDOPTQ2.js} +7 -7
- package/dist/{chunk-EVBRWESV.js.map → chunk-ATDOPTQ2.js.map} +1 -1
- package/dist/{chunk-CTPYM52J.js → chunk-BKHGXHCJ.js} +3 -3
- package/dist/{chunk-CTPYM52J.js.map → chunk-BKHGXHCJ.js.map} +1 -1
- package/dist/{chunk-HQLFHGPV.js → chunk-BXBXCVSQ.js} +5 -5
- package/dist/{chunk-HQLFHGPV.js.map → chunk-BXBXCVSQ.js.map} +1 -1
- package/dist/{chunk-OZP22OV3.js → chunk-C76E3NHH.js} +3 -3
- package/dist/{chunk-OZP22OV3.js.map → chunk-C76E3NHH.js.map} +1 -1
- package/dist/{chunk-45UU2OKF.js → chunk-DYSSY56M.js} +4 -4
- package/dist/{chunk-45UU2OKF.js.map → chunk-DYSSY56M.js.map} +1 -1
- package/dist/{chunk-WSNBAH3Z.js → chunk-FH4EVOMN.js} +3 -3
- package/dist/{chunk-WSNBAH3Z.js.map → chunk-FH4EVOMN.js.map} +1 -1
- package/dist/{chunk-IS6CEQF7.js → chunk-GDLT2GGX.js} +3 -3
- package/dist/{chunk-IS6CEQF7.js.map → chunk-GDLT2GGX.js.map} +1 -1
- package/dist/{chunk-JYGEHJU4.js → chunk-JKSDTWEC.js} +3 -3
- package/dist/{chunk-JYGEHJU4.js.map → chunk-JKSDTWEC.js.map} +1 -1
- package/dist/{chunk-CSONBCDW.js → chunk-JRJYZHQE.js} +3 -3
- package/dist/{chunk-CSONBCDW.js.map → chunk-JRJYZHQE.js.map} +1 -1
- package/dist/{chunk-QLY2NOJT.js → chunk-KAWAAVGL.js} +3 -3
- package/dist/{chunk-QLY2NOJT.js.map → chunk-KAWAAVGL.js.map} +1 -1
- package/dist/{chunk-YHTFDUAJ.js → chunk-LBYLBSVN.js} +4 -4
- package/dist/{chunk-YHTFDUAJ.js.map → chunk-LBYLBSVN.js.map} +1 -1
- package/dist/{chunk-QGDRC7U7.js → chunk-MNI3ZVUN.js} +3 -3
- package/dist/{chunk-QGDRC7U7.js.map → chunk-MNI3ZVUN.js.map} +1 -1
- package/dist/{chunk-6LQHXT4S.js → chunk-NGT46BX2.js} +7 -7
- package/dist/{chunk-6LQHXT4S.js.map → chunk-NGT46BX2.js.map} +1 -1
- package/dist/{chunk-AD7KLDOA.js → chunk-NSZOUCAR.js} +4 -4
- package/dist/{chunk-AD7KLDOA.js.map → chunk-NSZOUCAR.js.map} +1 -1
- package/dist/{chunk-7AWWYJXA.js → chunk-OPON37ZR.js} +3 -3
- package/dist/{chunk-7AWWYJXA.js.map → chunk-OPON37ZR.js.map} +1 -1
- package/dist/{chunk-MFHGYANL.js → chunk-P3ZYGK5E.js} +4 -4
- package/dist/{chunk-MFHGYANL.js.map → chunk-P3ZYGK5E.js.map} +1 -1
- package/dist/{chunk-HWVRIO2E.js → chunk-QN5XSUBT.js} +4 -4
- package/dist/{chunk-HWVRIO2E.js.map → chunk-QN5XSUBT.js.map} +1 -1
- package/dist/{chunk-Y2ZCCAXG.js → chunk-QXHO52TF.js} +4 -4
- package/dist/{chunk-Y2ZCCAXG.js.map → chunk-QXHO52TF.js.map} +1 -1
- package/dist/{chunk-TLT4HZMM.js → chunk-RI6FUYJT.js} +3 -3
- package/dist/{chunk-TLT4HZMM.js.map → chunk-RI6FUYJT.js.map} +1 -1
- package/dist/{chunk-ZACN2Z2L.js → chunk-ROW2E5ZY.js} +4 -4
- package/dist/{chunk-ZACN2Z2L.js.map → chunk-ROW2E5ZY.js.map} +1 -1
- package/dist/{chunk-D7UQKKFR.js → chunk-SBZZEW6D.js} +4 -4
- package/dist/{chunk-D7UQKKFR.js.map → chunk-SBZZEW6D.js.map} +1 -1
- package/dist/{chunk-OFDFDY2F.js → chunk-TVNO5MCL.js} +3 -3
- package/dist/{chunk-OFDFDY2F.js.map → chunk-TVNO5MCL.js.map} +1 -1
- package/dist/{chunk-ONHJKZ6J.js → chunk-UME7NAC5.js} +7 -7
- package/dist/{chunk-ONHJKZ6J.js.map → chunk-UME7NAC5.js.map} +1 -1
- package/dist/{chunk-P4WJ2JMF.js → chunk-VS2GO7GL.js} +16 -8
- package/dist/chunk-VS2GO7GL.js.map +1 -0
- package/dist/{chunk-RORNWRSU.js → chunk-WDL6T5RX.js} +3 -3
- package/dist/{chunk-RORNWRSU.js.map → chunk-WDL6T5RX.js.map} +1 -1
- package/dist/{chunk-7CU5YP4T.js → chunk-X7WJ2TAE.js} +4 -4
- package/dist/{chunk-7CU5YP4T.js.map → chunk-X7WJ2TAE.js.map} +1 -1
- package/dist/{chunk-I2NUWNDF.js → chunk-XK4UZHW7.js} +3 -3
- package/dist/{chunk-I2NUWNDF.js.map → chunk-XK4UZHW7.js.map} +1 -1
- package/dist/{chunk-HMMOUH2W.js → chunk-XYLGWKPG.js} +3 -3
- package/dist/{chunk-HMMOUH2W.js.map → chunk-XYLGWKPG.js.map} +1 -1
- package/dist/{chunk-SMKHH7X6.js → chunk-ZJLNYJCD.js} +5 -5
- package/dist/{chunk-SMKHH7X6.js.map → chunk-ZJLNYJCD.js.map} +1 -1
- package/dist/components/cart/index.js +1 -1
- package/dist/components/common/index.js +1 -1
- package/dist/components/drawer/index.js +12 -12
- package/dist/components/home/HomePageRenderer.d.ts +1 -1
- package/dist/components/home/HomePageRenderer.d.ts.map +1 -1
- package/dist/components/home/index.js +17 -17
- package/dist/components/layout/index.js +4 -4
- package/dist/components/product/index.js +14 -14
- package/dist/components/store/index.js +13 -13
- package/dist/dev/editor/index.js +1 -1
- package/dist/dev/index.js +1 -1
- package/dist/{document-class-4OCKM577.js → document-class-NJGMU7RC.js} +11 -11
- package/dist/{document-class-4OCKM577.js.map → document-class-NJGMU7RC.js.map} +1 -1
- package/dist/hooks/index.js +12 -12
- package/dist/hooks/useGtm.js +12 -12
- package/dist/hooks/useMoney.js +12 -12
- package/dist/hooks/useStore.js +12 -12
- package/dist/hooks/useUser.js +3 -3
- package/dist/index.js +12 -12
- package/dist/{navigation-BFBWKBGA.js → navigation-ATNB3OMU.js} +5 -5
- package/dist/{navigation-BFBWKBGA.js.map → navigation-ATNB3OMU.js.map} +1 -1
- package/dist/{navigation-LZNDPCZR.js → navigation-XB2AA2QD.js} +4 -4
- package/dist/{navigation-LZNDPCZR.js.map → navigation-XB2AA2QD.js.map} +1 -1
- package/dist/{not-found-4MCKSS62.js → not-found-6PQMIL5E.js} +15 -15
- package/dist/{not-found-4MCKSS62.js.map → not-found-6PQMIL5E.js.map} +1 -1
- package/dist/providers/index.js +12 -12
- package/dist/routes/account/orders/single/OrderHeader.d.ts.map +1 -1
- package/dist/routes/account/orders.js +4 -4
- package/dist/routes/account/types.d.ts +1 -0
- package/dist/routes/account/types.d.ts.map +1 -1
- package/dist/routes/account.js +13 -13
- package/dist/routes/blog.js +8 -8
- package/dist/routes/brands.js +4 -4
- package/dist/routes/cart.js +21 -21
- package/dist/routes/home.js +18 -18
- package/dist/routes/index.js +3 -3
- package/dist/routes/loyalty.js +5 -5
- package/dist/routes/page.js +4 -4
- package/dist/routes/product-listing.js +19 -19
- package/dist/routes/product.js +17 -17
- package/dist/routes/seo-redirects.js +3 -3
- package/dist/routes/testimonials.js +2 -2
- package/dist/routes/thank-you.js +4 -4
- package/dist/skeleton.js +18 -18
- package/dist/{store-lookup-6JBMBBBF.js → store-lookup-MDUKB5VN.js} +8 -8
- package/dist/{store-lookup-6JBMBBBF.js.map → store-lookup-MDUKB5VN.js.map} +1 -1
- package/dist/tanstack.js +11 -11
- package/dist/utils/index.js +2 -2
- package/package.json +1 -1
- package/tailwind/components/home/HomePageRenderer.tsx.txt +20 -1
- package/tailwind/routes/account/orders/single/OrderHeader.tsx.txt +21 -4
- package/tailwind/routes/account/types.ts.txt +1 -0
- package/dist/OrderSinglePage-3XHUQGEW.js.map +0 -1
- package/dist/chunk-P4WJ2JMF.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/routes/account/orders/loader.ts","../src/routes/account/orders/index.tsx"],"names":[],"mappings":"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","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/routes/account/orders/loader.ts","../src/routes/account/orders/index.tsx"],"names":[],"mappings":"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","file":"chunk-ATDOPTQ2.js","sourcesContent":["import { order } from '../../../api/order';\nimport { getTwilightContext } from '../../../twilight/context';\nimport { RouteId } from '../../../router/route-ids';\nimport { orThrow, orUnauthorized, unauthorized } from '../../../providers/NavigationProvider';\nimport { getAuthToken } from '../../../api/client';\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 if (!getAuthToken()) throw unauthorized();\n const query = ctx.query;\n const isPending = query?.status === 'pending';\n const response = await orUnauthorized(\n order.list({\n // Only decides the empty state; <salla-orders> applies its own review filter (`?tab=waiting`).\n status: query?.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 ? i18n.t('common.titles.pending_orders') : i18n.t('common.titles.orders'),\n slug: RouteId.CUSTOMER_ORDERS_INDEX,\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 if (!getAuthToken()) throw unauthorized();\n const [data, componentsOrder] = await Promise.all([\n order.findOrThrow(params.id),\n orThrow(orUnauthorized(order.findForComponents(params.id))),\n ]);\n const i18n = getTwilightContext().i18n;\n return {\n page: {\n slug: RouteId.CUSTOMER_ORDERS_SINGLE,\n id: String(params.id),\n title: i18n\n .t('pages.orders.order_details')\n .replace(':id', String(data.order.reference_id ?? params.id)),\n },\n order: data.order,\n componentsOrder,\n };\n}\n","import type { HeadDescriptor } from '../../../utils/head';\nimport { buildHreflangAlternates } from '../../../utils/baseHead';\n\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 = lazyComponent(() =>\n import('./OrdersPage').then((m) => ({ default: m.OrdersPage }))\n);\nconst LazyOrderSinglePage = lazyComponent(() =>\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';\nimport { lazyComponent } from '../../../utils/lazy-component';\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 // ordersLoader already merges the result of `extend`; calling it again here ran it twice.\n return ordersLoader({ query, with_items: ctx.with_items }, extend);\n}\n\nfunction ordersHead(ctx: TwilightContext, data: OrdersPageProps): HeadDescriptor {\n const isPending = data.query?.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"]}
|
|
@@ -6,7 +6,7 @@ export { BlogSkeleton, BreadcrumbSkeleton, CustomerLayoutSkeleton, CustomerPageS
|
|
|
6
6
|
|
|
7
7
|
// src/components/common/lazy.ts
|
|
8
8
|
var LazyBreadcrumb = lazyComponent(
|
|
9
|
-
() => import('./Breadcrumb-
|
|
9
|
+
() => import('./Breadcrumb-I6RHU7TL.js').then((m) => ({ default: m.Breadcrumb }))
|
|
10
10
|
);
|
|
11
11
|
var LazyNoContent = lazyComponent(
|
|
12
12
|
() => import('./NoContent-7A7OR2NZ.js').then((m) => ({ default: m.NoContent }))
|
|
@@ -155,5 +155,5 @@ function DeferredData({ promise, fallback, children }) {
|
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
export { DeferredData, Image, LazyBreadcrumb, LazyCurrencySymbol, LazyErrorPage, LazyNoContent, LazyRenderWhenVisible, resolveDeferred };
|
|
158
|
-
//# sourceMappingURL=chunk-
|
|
159
|
-
//# sourceMappingURL=chunk-
|
|
158
|
+
//# sourceMappingURL=chunk-BKHGXHCJ.js.map
|
|
159
|
+
//# sourceMappingURL=chunk-BKHGXHCJ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/common/lazy.ts","../src/components/common/Image.tsx","../src/components/common/DeferredData.tsx"],"names":["Image","memo","DeferredRenderer","jsx"],"mappings":"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","file":"chunk-CTPYM52J.js","sourcesContent":["import { lazyComponent } from '../../utils/lazy-component';\n\n/**\n * Lazy-loaded common components\n * Use these for code-splitting non-critical components\n *\n * NOTE: Skeleton components are sourced from @salla.sa/twilight-components-react\n * because they must render instantly during route transitions.\n */\nexport const LazyBreadcrumb = lazyComponent(() =>\n import('./Breadcrumb').then((m) => ({ default: m.Breadcrumb }))\n);\n\nexport const LazyNoContent = lazyComponent(() =>\n import('./NoContent').then((m) => ({ default: m.NoContent }))\n);\n\nexport const LazyRenderWhenVisible = lazyComponent(() =>\n import('./RenderWhenVisible').then((m) => ({ default: m.RenderWhenVisible }))\n);\n\nexport const LazyCurrencySymbol = lazyComponent(() =>\n import('./CurrencySymbol').then((m) => ({ default: m.CurrencySymbol }))\n);\n\nexport const LazyErrorPage = lazyComponent(() =>\n import('./ErrorPage').then((m) => ({ default: m.ErrorPage }))\n);\n","import { memo } from 'react';\nimport { getCdnImageSrcSet, getCdnImageUrl } from '../../utils/cdn-image';\n\nexport interface ImageProps extends React.ImgHTMLAttributes<HTMLImageElement> {\n /** Image source URL */\n src?: string;\n /** Alt text for accessibility */\n alt: string;\n /** Whether this image is above the fold / LCP candidate */\n priority?: boolean;\n /** Aspect ratio for CLS prevention (e.g. \"16/9\", \"1/1\", \"4/3\") */\n aspectRatio?: string;\n /** Object fit mode */\n objectFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';\n /** Mobile image source for <picture> element */\n mobileSrc?: string;\n /** Mobile breakpoint for <source> media query (default: 768px) */\n mobileBreakpoint?: number;\n /** Skip the wrapper div */\n noWrapper?: boolean;\n /**\n * CDN widths for a density `srcset`. Pass `sizes` so the browser picks a\n * candidate close to the displayed CSS size.\n */\n srcSetWidths?: readonly number[];\n}\n\n/**\n * Optimized Image component with native browser lazy loading.\n *\n * - Uses `loading=\"lazy\"` + `decoding=\"async\"` by default for below-the-fold images.\n * - Uses `loading=\"eager\"` + `fetchPriority=\"high\"` for priority (above-the-fold / LCP) images.\n * - Supports responsive `<picture>` with mobile source.\n * - Provides `aspectRatio` for CLS prevention.\n * - When `srcSetWidths` + `sizes` are set, emits a sized CDN `srcset`.\n */\nexport const Image = memo(function Image({\n src,\n alt,\n priority = false,\n aspectRatio,\n objectFit = 'cover',\n mobileSrc,\n mobileBreakpoint = 768,\n noWrapper = false,\n className = '',\n style,\n width,\n height,\n sizes,\n srcSet: srcSetProp,\n srcSetWidths,\n ...rest\n}: ImageProps) {\n if (!src) return null;\n\n const generatedSrcSet =\n srcSetProp || (srcSetWidths?.length ? getCdnImageSrcSet(src, srcSetWidths) : undefined);\n const generatedMobileSrcSet =\n srcSetWidths?.length && mobileSrc ? getCdnImageSrcSet(mobileSrc, srcSetWidths) : undefined;\n const cdnWidth = srcSetWidths?.length\n ? width != null && srcSetWidths.includes(Number(width))\n ? Number(width)\n : srcSetWidths[0]\n : width;\n // Width-only CDN URLs so `src` matches a srcset candidate for preload.\n const cdnOptions = generatedSrcSet ? { width: cdnWidth } : { width: cdnWidth, height };\n\n const optimizedSrc = getCdnImageUrl(src, cdnOptions);\n const optimizedMobileSrc = getCdnImageUrl(mobileSrc, cdnOptions);\n\n const objectFitClass = `object-${objectFit}`;\n const imgClasses = [className, objectFitClass].filter(Boolean).join(' ');\n\n const loadingProps: React.ImgHTMLAttributes<HTMLImageElement> = priority\n ? { loading: 'eager' as const, fetchPriority: 'high' as const, decoding: 'sync' as const }\n : { loading: 'lazy' as const, decoding: 'async' as const };\n\n const hasWrapper = !noWrapper && !!aspectRatio;\n\n const img = (\n <img\n src={optimizedSrc}\n alt={alt}\n className={imgClasses}\n width={width}\n height={height}\n sizes={sizes}\n srcSet={generatedSrcSet}\n // With a wrapper, `style` goes to the wrapper; otherwise it must land on the <img>.\n style={hasWrapper ? undefined : style}\n {...loadingProps}\n {...rest}\n />\n );\n\n const imgElement = optimizedMobileSrc ? (\n <picture>\n <source\n media={`(max-width: ${mobileBreakpoint}px)`}\n srcSet={generatedMobileSrcSet || optimizedMobileSrc}\n sizes={generatedMobileSrcSet ? sizes : undefined}\n />\n {img}\n </picture>\n ) : (\n img\n );\n\n if (!hasWrapper) {\n return imgElement;\n }\n\n return (\n <div className=\"relative overflow-hidden\" style={{ aspectRatio, ...style }}>\n {imgElement}\n </div>\n );\n});\n","import { Suspense, memo, use, type ReactNode } from 'react';\n\nexport interface DeferredDataProps<T> {\n promise: Promise<T> | T;\n fallback: ReactNode;\n children: (data: T) => ReactNode;\n}\n\nconst DEFERRED_KEY = Symbol.for('twilight.deferred');\n\ninterface DeferredState<T> {\n status: 'pending' | 'success' | 'error';\n value?: T;\n error?: unknown;\n}\n\nexport interface DeferredPromise<T> extends Promise<T> {\n [DEFERRED_KEY]?: DeferredState<T>;\n}\n\nconst seenPromises = typeof WeakSet !== 'undefined' ? new WeakSet() : null;\n\nfunction defer<T>(promise: Promise<T>): DeferredPromise<T> {\n const existing = (promise as DeferredPromise<T>)[DEFERRED_KEY];\n if (existing) return promise as DeferredPromise<T>;\n\n const state: DeferredState<T> = { status: 'pending' };\n\n const deferred = promise as DeferredPromise<T>;\n deferred[DEFERRED_KEY] = state;\n\n promise.then(\n (value) => {\n state.status = 'success';\n state.value = value;\n },\n (error) => {\n state.status = 'error';\n state.error = error;\n }\n );\n\n return deferred;\n}\n\nconst DeferredRenderer = memo(function DeferredRenderer<T>({\n promise,\n children,\n}: {\n promise: DeferredPromise<T>;\n children: (data: T) => ReactNode;\n}) {\n const state = promise[DEFERRED_KEY];\n\n if (state?.status === 'success') {\n return children(state.value!);\n }\n\n if (state?.status === 'error') {\n throw state.error;\n }\n\n const data = use(promise);\n return children(data);\n}) as <T>(props: { promise: DeferredPromise<T>; children: (data: T) => ReactNode }) => ReactNode;\n\nfunction DeferredFallback<T>({\n promise,\n fallback,\n children,\n}: {\n promise: DeferredPromise<T>;\n fallback: ReactNode;\n children: (data: T) => ReactNode;\n}) {\n const state = promise[DEFERRED_KEY];\n if (state?.status === 'success') {\n return children(state.value!);\n }\n return <>{fallback}</>;\n}\n\nexport function resolveDeferred<T>(\n promiseOrValue: Promise<T> | T | undefined\n): T | Promise<T> | undefined {\n if (promiseOrValue == null || !(promiseOrValue instanceof Promise)) return promiseOrValue;\n const deferred = defer(promiseOrValue);\n const state = deferred[DEFERRED_KEY];\n if (state?.status === 'success') return state.value as T;\n return promiseOrValue;\n}\n\nexport function DeferredData<T>({ promise, fallback, children }: DeferredDataProps<T>) {\n if (!(promise instanceof Promise)) {\n return children(promise);\n }\n\n if (seenPromises && promise instanceof Promise) seenPromises.add(promise);\n\n const deferred = defer(promise);\n const state = deferred[DEFERRED_KEY];\n\n if (state?.status === 'success') {\n return children(state.value!);\n }\n\n if (state?.status === 'error') {\n throw state.error;\n }\n\n return (\n <Suspense\n fallback={\n <DeferredFallback promise={deferred} fallback={fallback}>\n {children}\n </DeferredFallback>\n }\n >\n <DeferredRenderer promise={deferred}>{children}</DeferredRenderer>\n </Suspense>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/common/lazy.ts","../src/components/common/Image.tsx","../src/components/common/DeferredData.tsx"],"names":["Image","memo","DeferredRenderer","jsx"],"mappings":"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","file":"chunk-BKHGXHCJ.js","sourcesContent":["import { lazyComponent } from '../../utils/lazy-component';\n\n/**\n * Lazy-loaded common components\n * Use these for code-splitting non-critical components\n *\n * NOTE: Skeleton components are sourced from @salla.sa/twilight-components-react\n * because they must render instantly during route transitions.\n */\nexport const LazyBreadcrumb = lazyComponent(() =>\n import('./Breadcrumb').then((m) => ({ default: m.Breadcrumb }))\n);\n\nexport const LazyNoContent = lazyComponent(() =>\n import('./NoContent').then((m) => ({ default: m.NoContent }))\n);\n\nexport const LazyRenderWhenVisible = lazyComponent(() =>\n import('./RenderWhenVisible').then((m) => ({ default: m.RenderWhenVisible }))\n);\n\nexport const LazyCurrencySymbol = lazyComponent(() =>\n import('./CurrencySymbol').then((m) => ({ default: m.CurrencySymbol }))\n);\n\nexport const LazyErrorPage = lazyComponent(() =>\n import('./ErrorPage').then((m) => ({ default: m.ErrorPage }))\n);\n","import { memo } from 'react';\nimport { getCdnImageSrcSet, getCdnImageUrl } from '../../utils/cdn-image';\n\nexport interface ImageProps extends React.ImgHTMLAttributes<HTMLImageElement> {\n /** Image source URL */\n src?: string;\n /** Alt text for accessibility */\n alt: string;\n /** Whether this image is above the fold / LCP candidate */\n priority?: boolean;\n /** Aspect ratio for CLS prevention (e.g. \"16/9\", \"1/1\", \"4/3\") */\n aspectRatio?: string;\n /** Object fit mode */\n objectFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';\n /** Mobile image source for <picture> element */\n mobileSrc?: string;\n /** Mobile breakpoint for <source> media query (default: 768px) */\n mobileBreakpoint?: number;\n /** Skip the wrapper div */\n noWrapper?: boolean;\n /**\n * CDN widths for a density `srcset`. Pass `sizes` so the browser picks a\n * candidate close to the displayed CSS size.\n */\n srcSetWidths?: readonly number[];\n}\n\n/**\n * Optimized Image component with native browser lazy loading.\n *\n * - Uses `loading=\"lazy\"` + `decoding=\"async\"` by default for below-the-fold images.\n * - Uses `loading=\"eager\"` + `fetchPriority=\"high\"` for priority (above-the-fold / LCP) images.\n * - Supports responsive `<picture>` with mobile source.\n * - Provides `aspectRatio` for CLS prevention.\n * - When `srcSetWidths` + `sizes` are set, emits a sized CDN `srcset`.\n */\nexport const Image = memo(function Image({\n src,\n alt,\n priority = false,\n aspectRatio,\n objectFit = 'cover',\n mobileSrc,\n mobileBreakpoint = 768,\n noWrapper = false,\n className = '',\n style,\n width,\n height,\n sizes,\n srcSet: srcSetProp,\n srcSetWidths,\n ...rest\n}: ImageProps) {\n if (!src) return null;\n\n const generatedSrcSet =\n srcSetProp || (srcSetWidths?.length ? getCdnImageSrcSet(src, srcSetWidths) : undefined);\n const generatedMobileSrcSet =\n srcSetWidths?.length && mobileSrc ? getCdnImageSrcSet(mobileSrc, srcSetWidths) : undefined;\n const cdnWidth = srcSetWidths?.length\n ? width != null && srcSetWidths.includes(Number(width))\n ? Number(width)\n : srcSetWidths[0]\n : width;\n // Width-only CDN URLs so `src` matches a srcset candidate for preload.\n const cdnOptions = generatedSrcSet ? { width: cdnWidth } : { width: cdnWidth, height };\n\n const optimizedSrc = getCdnImageUrl(src, cdnOptions);\n const optimizedMobileSrc = getCdnImageUrl(mobileSrc, cdnOptions);\n\n const objectFitClass = `object-${objectFit}`;\n const imgClasses = [className, objectFitClass].filter(Boolean).join(' ');\n\n const loadingProps: React.ImgHTMLAttributes<HTMLImageElement> = priority\n ? { loading: 'eager' as const, fetchPriority: 'high' as const, decoding: 'sync' as const }\n : { loading: 'lazy' as const, decoding: 'async' as const };\n\n const hasWrapper = !noWrapper && !!aspectRatio;\n\n const img = (\n <img\n src={optimizedSrc}\n alt={alt}\n className={imgClasses}\n width={width}\n height={height}\n sizes={sizes}\n srcSet={generatedSrcSet}\n // With a wrapper, `style` goes to the wrapper; otherwise it must land on the <img>.\n style={hasWrapper ? undefined : style}\n {...loadingProps}\n {...rest}\n />\n );\n\n const imgElement = optimizedMobileSrc ? (\n <picture>\n <source\n media={`(max-width: ${mobileBreakpoint}px)`}\n srcSet={generatedMobileSrcSet || optimizedMobileSrc}\n sizes={generatedMobileSrcSet ? sizes : undefined}\n />\n {img}\n </picture>\n ) : (\n img\n );\n\n if (!hasWrapper) {\n return imgElement;\n }\n\n return (\n <div className=\"relative overflow-hidden\" style={{ aspectRatio, ...style }}>\n {imgElement}\n </div>\n );\n});\n","import { Suspense, memo, use, type ReactNode } from 'react';\n\nexport interface DeferredDataProps<T> {\n promise: Promise<T> | T;\n fallback: ReactNode;\n children: (data: T) => ReactNode;\n}\n\nconst DEFERRED_KEY = Symbol.for('twilight.deferred');\n\ninterface DeferredState<T> {\n status: 'pending' | 'success' | 'error';\n value?: T;\n error?: unknown;\n}\n\nexport interface DeferredPromise<T> extends Promise<T> {\n [DEFERRED_KEY]?: DeferredState<T>;\n}\n\nconst seenPromises = typeof WeakSet !== 'undefined' ? new WeakSet() : null;\n\nfunction defer<T>(promise: Promise<T>): DeferredPromise<T> {\n const existing = (promise as DeferredPromise<T>)[DEFERRED_KEY];\n if (existing) return promise as DeferredPromise<T>;\n\n const state: DeferredState<T> = { status: 'pending' };\n\n const deferred = promise as DeferredPromise<T>;\n deferred[DEFERRED_KEY] = state;\n\n promise.then(\n (value) => {\n state.status = 'success';\n state.value = value;\n },\n (error) => {\n state.status = 'error';\n state.error = error;\n }\n );\n\n return deferred;\n}\n\nconst DeferredRenderer = memo(function DeferredRenderer<T>({\n promise,\n children,\n}: {\n promise: DeferredPromise<T>;\n children: (data: T) => ReactNode;\n}) {\n const state = promise[DEFERRED_KEY];\n\n if (state?.status === 'success') {\n return children(state.value!);\n }\n\n if (state?.status === 'error') {\n throw state.error;\n }\n\n const data = use(promise);\n return children(data);\n}) as <T>(props: { promise: DeferredPromise<T>; children: (data: T) => ReactNode }) => ReactNode;\n\nfunction DeferredFallback<T>({\n promise,\n fallback,\n children,\n}: {\n promise: DeferredPromise<T>;\n fallback: ReactNode;\n children: (data: T) => ReactNode;\n}) {\n const state = promise[DEFERRED_KEY];\n if (state?.status === 'success') {\n return children(state.value!);\n }\n return <>{fallback}</>;\n}\n\nexport function resolveDeferred<T>(\n promiseOrValue: Promise<T> | T | undefined\n): T | Promise<T> | undefined {\n if (promiseOrValue == null || !(promiseOrValue instanceof Promise)) return promiseOrValue;\n const deferred = defer(promiseOrValue);\n const state = deferred[DEFERRED_KEY];\n if (state?.status === 'success') return state.value as T;\n return promiseOrValue;\n}\n\nexport function DeferredData<T>({ promise, fallback, children }: DeferredDataProps<T>) {\n if (!(promise instanceof Promise)) {\n return children(promise);\n }\n\n if (seenPromises && promise instanceof Promise) seenPromises.add(promise);\n\n const deferred = defer(promise);\n const state = deferred[DEFERRED_KEY];\n\n if (state?.status === 'success') {\n return children(state.value!);\n }\n\n if (state?.status === 'error') {\n throw state.error;\n }\n\n return (\n <Suspense\n fallback={\n <DeferredFallback promise={deferred} fallback={fallback}>\n {children}\n </DeferredFallback>\n }\n >\n <DeferredRenderer promise={deferred}>{children}</DeferredRenderer>\n </Suspense>\n );\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { reorder, useLiveBlockMoves } from './chunk-IXHM24Z4.js';
|
|
2
|
-
import { HomeComponentRenderer, ReorderProducts } from './chunk-
|
|
3
|
-
import { home } from './chunk-
|
|
4
|
-
import { useDevHomeBlocks } from './chunk-
|
|
2
|
+
import { HomeComponentRenderer, ReorderProducts } from './chunk-VS2GO7GL.js';
|
|
3
|
+
import { home } from './chunk-4LTS5AZ3.js';
|
|
4
|
+
import { useDevHomeBlocks } from './chunk-JKSDTWEC.js';
|
|
5
5
|
import { storePageUrl, buildHreflangAlternates } from './chunk-RYGEIQWO.js';
|
|
6
6
|
import { RouteId } from './chunk-OUW6WESU.js';
|
|
7
7
|
import { HookSlot } from './chunk-5XDPAKF5.js';
|
|
@@ -104,5 +104,5 @@ function head(ctx) {
|
|
|
104
104
|
var Home = { id: RouteId.INDEX, loader, head, Component: HomePage };
|
|
105
105
|
|
|
106
106
|
export { Home, HomeSkeleton, homeLoader };
|
|
107
|
-
//# sourceMappingURL=chunk-
|
|
108
|
-
//# sourceMappingURL=chunk-
|
|
107
|
+
//# sourceMappingURL=chunk-BXBXCVSQ.js.map
|
|
108
|
+
//# sourceMappingURL=chunk-BXBXCVSQ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/routes/home/loader.ts","../src/routes/home/HomePage.tsx","../src/routes/home/index.tsx"],"names":["HomeSkeleton","HomePage"],"mappings":"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","file":"chunk-HQLFHGPV.js","sourcesContent":["import { getTwilightContext } from '../../twilight/context';\nimport { home } from '../../api/home';\nimport type { HomeComponentData } from '../../types';\nimport { RouteId } from '../../router/route-ids';\n\nexport interface HomeLoaderData {\n locale: string;\n components: HomeComponentData[];\n page: { slug: string };\n}\n\nexport async function homeLoader(ctx?: { locale?: string }): Promise<HomeLoaderData> {\n const { queryClient } = getTwilightContext();\n const components = await queryClient.ensureQueryData(home.queries.components());\n const result = {\n locale: ctx?.locale || 'ar',\n components: components.map((comp) => ({\n ...comp,\n path: comp.path?.replace('home.', '') || comp.path,\n })),\n page: { slug: RouteId.INDEX },\n };\n return result;\n}\n","import { memo, useCallback, useState } from 'react';\nimport { useDevHomeBlocks } from '../../dev/dev-settings-store';\nimport { HookSlot } from '../../hooks';\nimport { HomeComponentRenderer, ReorderProducts } from '../../components/home';\nimport { reorder, useLiveBlockMoves } from '../../components/live-editor/moves';\nimport type { HomePageProps } from './types';\nimport type { HomeComponentData } from '../../types';\nimport { Pulse } from '@salla.sa/twilight-components-react';\n\nexport const HomeSkeleton = memo(function HomeSkeleton() {\n return (\n <>\n <div className=\"s-block container skeleton-block-hero\">\n <Pulse className=\"h-64 sm:h-80 rounded-md\" />\n </div>\n <div className=\"s-block container skeleton-block-products\">\n <Pulse className=\"h-10 w-48 mb-4\" />\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-4\">\n {[1, 2, 3, 4].map((i) => (\n <Pulse key={i} className=\"h-56\" />\n ))}\n </div>\n </div>\n <div className=\"s-block container skeleton-block-products\">\n <Pulse className=\"h-10 w-48 mb-4\" />\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-4\">\n {[1, 2, 3, 4].map((i) => (\n <Pulse key={i} className=\"h-56\" />\n ))}\n </div>\n </div>\n </>\n );\n});\n\n/** As on Twig, a home page with no blocks lists the store's latest products instead. */\nconst LATEST_PRODUCTS: HomeComponentData = { path: 'latest-products' };\n\n/** The blocks' places in the store's order: 0, 1, 2… */\nconst storeOrder = (blocks: readonly unknown[]) => Array.from(blocks, (_, at) => at);\n\nexport const HomePage = memo(function HomePage({ components = [] }: HomePageProps) {\n // Dev-mode only: the dev editor's layout replaces the store's blocks while it\n // is on. No-op passthrough in production builds.\n const renderedComponents = useDevHomeBlocks(components);\n // The theme editor's preview moves blocks in place while the editor saves the\n // order; blocks from the server (a new page, a reload) start over from theirs.\n const [moved, setMoved] = useState<{ source: HomeComponentData[]; order: number[] } | null>(null);\n const order = moved?.source === renderedComponents ? moved.order : null;\n const onMove = useCallback(\n (from: number, to: number) =>\n setMoved((prev) => ({\n source: renderedComponents,\n order: reorder(\n prev?.source === renderedComponents ? prev.order : storeOrder(renderedComponents),\n from,\n to\n ),\n })),\n [renderedComponents]\n );\n useLiveBlockMoves(onMove);\n const placed = order ?? storeOrder(renderedComponents);\n\n return (\n <>\n <HookSlot name=\"home:start\" />\n <HookSlot name=\"home:content\" />\n {placed.map((at, index) => {\n const data = renderedComponents[at];\n // `data.key` is the twilight.json catalog id, shared by every placement\n // of that block. Platform blocks send null. The block's place in the\n // store's order is unique and stays with it when the preview moves it, so\n // a move keeps its state; a dev layout block keeps its own id.\n return <HomeComponentRenderer key={data.__dev_id ?? at} data={data} index={index} />;\n })}\n {!renderedComponents.length && (\n <HomeComponentRenderer data={LATEST_PRODUCTS} index={0} editable={false} />\n )}\n <HookSlot name=\"home:end\" />\n <ReorderProducts />\n </>\n );\n});\n\nexport { HomePage as default };\n","import type { HeadDescriptor } from '../../utils/head';\nimport { buildHreflangAlternates, storePageUrl } from '../../utils/baseHead';\nimport type { HomeLoaderData } from './loader';\nimport { homeLoader } from './loader';\nimport type { TwilightContext } from '../../twilight/context';\nimport { HomePage } from './HomePage';\nimport { RouteId } from '../../router/route-ids';\n\nexport { HomeSkeleton } from './HomePage';\nexport { registerHomeComponents, DefaultHomeComponents } from '../../components/home/register';\nexport { registerHomeComponentConfig } from '../../components/home';\nexport type { HomePageProps } from './types';\nexport type { HomeLoaderData } from './loader';\nexport type {\n HomeComponentsProps,\n AnyHomeComponent,\n HomeComponentConfig,\n} from '../../components/home';\n\nfunction loader(_ctx?: { locale?: string }): Promise<HomeLoaderData> {\n return homeLoader({ locale: _ctx?.locale });\n}\n\nfunction head(ctx: TwilightContext): HeadDescriptor {\n const store = ctx.settings?.store;\n if (!store) return {};\n\n const title = store.meta?.title ?? store.name;\n const description = store.meta?.description ?? store.description;\n const keywords = store.meta?.keywords;\n // `/ar`, like Twig, where store.url reads `/ar/`.\n const url = storePageUrl(ctx.settings, ctx.location.pathname) ?? store.url;\n\n return {\n title,\n description,\n keywords,\n canonical: url,\n openGraph: {\n type: 'website',\n title,\n description,\n images: store.logo,\n url,\n },\n twitter: {\n card: 'summary_large_image',\n title,\n description,\n images: store.logo,\n },\n alternateLanguages: buildHreflangAlternates(ctx.settings, ctx.location.pathname),\n };\n}\n\nexport const Home = { id: RouteId.INDEX, loader, head, Component: HomePage } as const;\n\nexport { homeLoader };\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/routes/home/loader.ts","../src/routes/home/HomePage.tsx","../src/routes/home/index.tsx"],"names":["HomeSkeleton","HomePage"],"mappings":"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","file":"chunk-BXBXCVSQ.js","sourcesContent":["import { getTwilightContext } from '../../twilight/context';\nimport { home } from '../../api/home';\nimport type { HomeComponentData } from '../../types';\nimport { RouteId } from '../../router/route-ids';\n\nexport interface HomeLoaderData {\n locale: string;\n components: HomeComponentData[];\n page: { slug: string };\n}\n\nexport async function homeLoader(ctx?: { locale?: string }): Promise<HomeLoaderData> {\n const { queryClient } = getTwilightContext();\n const components = await queryClient.ensureQueryData(home.queries.components());\n const result = {\n locale: ctx?.locale || 'ar',\n components: components.map((comp) => ({\n ...comp,\n path: comp.path?.replace('home.', '') || comp.path,\n })),\n page: { slug: RouteId.INDEX },\n };\n return result;\n}\n","import { memo, useCallback, useState } from 'react';\nimport { useDevHomeBlocks } from '../../dev/dev-settings-store';\nimport { HookSlot } from '../../hooks';\nimport { HomeComponentRenderer, ReorderProducts } from '../../components/home';\nimport { reorder, useLiveBlockMoves } from '../../components/live-editor/moves';\nimport type { HomePageProps } from './types';\nimport type { HomeComponentData } from '../../types';\nimport { Pulse } from '@salla.sa/twilight-components-react';\n\nexport const HomeSkeleton = memo(function HomeSkeleton() {\n return (\n <>\n <div className=\"s-block container skeleton-block-hero\">\n <Pulse className=\"h-64 sm:h-80 rounded-md\" />\n </div>\n <div className=\"s-block container skeleton-block-products\">\n <Pulse className=\"h-10 w-48 mb-4\" />\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-4\">\n {[1, 2, 3, 4].map((i) => (\n <Pulse key={i} className=\"h-56\" />\n ))}\n </div>\n </div>\n <div className=\"s-block container skeleton-block-products\">\n <Pulse className=\"h-10 w-48 mb-4\" />\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-4\">\n {[1, 2, 3, 4].map((i) => (\n <Pulse key={i} className=\"h-56\" />\n ))}\n </div>\n </div>\n </>\n );\n});\n\n/** As on Twig, a home page with no blocks lists the store's latest products instead. */\nconst LATEST_PRODUCTS: HomeComponentData = { path: 'latest-products' };\n\n/** The blocks' places in the store's order: 0, 1, 2… */\nconst storeOrder = (blocks: readonly unknown[]) => Array.from(blocks, (_, at) => at);\n\nexport const HomePage = memo(function HomePage({ components = [] }: HomePageProps) {\n // Dev-mode only: the dev editor's layout replaces the store's blocks while it\n // is on. No-op passthrough in production builds.\n const renderedComponents = useDevHomeBlocks(components);\n // The theme editor's preview moves blocks in place while the editor saves the\n // order; blocks from the server (a new page, a reload) start over from theirs.\n const [moved, setMoved] = useState<{ source: HomeComponentData[]; order: number[] } | null>(null);\n const order = moved?.source === renderedComponents ? moved.order : null;\n const onMove = useCallback(\n (from: number, to: number) =>\n setMoved((prev) => ({\n source: renderedComponents,\n order: reorder(\n prev?.source === renderedComponents ? prev.order : storeOrder(renderedComponents),\n from,\n to\n ),\n })),\n [renderedComponents]\n );\n useLiveBlockMoves(onMove);\n const placed = order ?? storeOrder(renderedComponents);\n\n return (\n <>\n <HookSlot name=\"home:start\" />\n <HookSlot name=\"home:content\" />\n {placed.map((at, index) => {\n const data = renderedComponents[at];\n // `data.key` is the twilight.json catalog id, shared by every placement\n // of that block. Platform blocks send null. The block's place in the\n // store's order is unique and stays with it when the preview moves it, so\n // a move keeps its state; a dev layout block keeps its own id.\n return <HomeComponentRenderer key={data.__dev_id ?? at} data={data} index={index} />;\n })}\n {!renderedComponents.length && (\n <HomeComponentRenderer data={LATEST_PRODUCTS} index={0} editable={false} />\n )}\n <HookSlot name=\"home:end\" />\n <ReorderProducts />\n </>\n );\n});\n\nexport { HomePage as default };\n","import type { HeadDescriptor } from '../../utils/head';\nimport { buildHreflangAlternates, storePageUrl } from '../../utils/baseHead';\nimport type { HomeLoaderData } from './loader';\nimport { homeLoader } from './loader';\nimport type { TwilightContext } from '../../twilight/context';\nimport { HomePage } from './HomePage';\nimport { RouteId } from '../../router/route-ids';\n\nexport { HomeSkeleton } from './HomePage';\nexport { registerHomeComponents, DefaultHomeComponents } from '../../components/home/register';\nexport { registerHomeComponentConfig } from '../../components/home';\nexport type { HomePageProps } from './types';\nexport type { HomeLoaderData } from './loader';\nexport type {\n HomeComponentsProps,\n AnyHomeComponent,\n HomeComponentConfig,\n} from '../../components/home';\n\nfunction loader(_ctx?: { locale?: string }): Promise<HomeLoaderData> {\n return homeLoader({ locale: _ctx?.locale });\n}\n\nfunction head(ctx: TwilightContext): HeadDescriptor {\n const store = ctx.settings?.store;\n if (!store) return {};\n\n const title = store.meta?.title ?? store.name;\n const description = store.meta?.description ?? store.description;\n const keywords = store.meta?.keywords;\n // `/ar`, like Twig, where store.url reads `/ar/`.\n const url = storePageUrl(ctx.settings, ctx.location.pathname) ?? store.url;\n\n return {\n title,\n description,\n keywords,\n canonical: url,\n openGraph: {\n type: 'website',\n title,\n description,\n images: store.logo,\n url,\n },\n twitter: {\n card: 'summary_large_image',\n title,\n description,\n images: store.logo,\n },\n alternateLanguages: buildHreflangAlternates(ctx.settings, ctx.location.pathname),\n };\n}\n\nexport const Home = { id: RouteId.INDEX, loader, head, Component: HomePage } as const;\n\nexport { homeLoader };\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { user } from './chunk-
|
|
1
|
+
import { user } from './chunk-7HZ6JQAJ.js';
|
|
2
2
|
import { getTwilightContext } from './chunk-6K34BCUP.js';
|
|
3
3
|
import { useQuery } from '@tanstack/react-query';
|
|
4
4
|
|
|
@@ -13,5 +13,5 @@ function useUser() {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export { useUser };
|
|
16
|
-
//# sourceMappingURL=chunk-
|
|
17
|
-
//# sourceMappingURL=chunk-
|
|
16
|
+
//# sourceMappingURL=chunk-C76E3NHH.js.map
|
|
17
|
+
//# sourceMappingURL=chunk-C76E3NHH.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks/useUser.ts"],"names":[],"mappings":";;;;AAUO,SAAS,OAAA,GAAyB;AACvC,EAAA,MAAM,KAAA,GAAQ,oBAAmB,CAAE,SAAA;AAEnC,EAAA,MAAM,QAAQ,QAAA,CAAS;AAAA,IACrB,GAAG,IAAA,CAAK,OAAA,CAAQ,OAAA,EAAQ;AAAA,IACxB,OAAA,EAAS,CAAC,CAAC,KAAA;AAAA,IACX,eAAA,EAAiB;AAAA,GAClB,CAAA;AAED,EAAA,OAAO,EAAE,GAAG,KAAA,EAAO,UAAA,EAAY,CAAC,CAAC,KAAA,EAAM;AACzC","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/hooks/useUser.ts"],"names":[],"mappings":";;;;AAUO,SAAS,OAAA,GAAyB;AACvC,EAAA,MAAM,KAAA,GAAQ,oBAAmB,CAAE,SAAA;AAEnC,EAAA,MAAM,QAAQ,QAAA,CAAS;AAAA,IACrB,GAAG,IAAA,CAAK,OAAA,CAAQ,OAAA,EAAQ;AAAA,IACxB,OAAA,EAAS,CAAC,CAAC,KAAA;AAAA,IACX,eAAA,EAAiB;AAAA,GAClB,CAAA;AAED,EAAA,OAAO,EAAE,GAAG,KAAA,EAAO,UAAA,EAAY,CAAC,CAAC,KAAA,EAAM;AACzC","file":"chunk-C76E3NHH.js","sourcesContent":["import { useQuery, type UseQueryResult } from '@tanstack/react-query';\nimport { getTwilightContext } from '../twilight/context';\nimport { user } from '../api/user';\nimport type { User } from '../types';\n\nexport type UseUserReturn = UseQueryResult<User | null> & {\n /** True when an auth token exists (regardless of query state). */\n isLoggedIn: boolean;\n};\n\nexport function useUser(): UseUserReturn {\n const token = getTwilightContext().authToken;\n\n const query = useQuery({\n ...user.queries.current(),\n enabled: !!token,\n placeholderData: null,\n });\n\n return { ...query, isLoggedIn: !!token };\n}\n"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { registry } from './chunk-Y32RHCOH.js';
|
|
2
|
-
import { useMoney, useNumber } from './chunk-
|
|
2
|
+
import { useMoney, useNumber } from './chunk-4XB425HW.js';
|
|
3
3
|
import { useAsset } from './chunk-Z653O7MX.js';
|
|
4
4
|
import { useWishlist } from './chunk-LFHYQ6AN.js';
|
|
5
5
|
import { useTranslation } from './chunk-TYNZ5B2B.js';
|
|
6
|
-
import { Image } from './chunk-
|
|
6
|
+
import { Image } from './chunk-BKHGXHCJ.js';
|
|
7
7
|
import { useTwilight } from './chunk-DF6FBKDN.js';
|
|
8
8
|
import { memo, useCallback, useMemo } from 'react';
|
|
9
9
|
import { SallaAddProductButton } from '@salla.sa/twilight-components-react/add-product-button';
|
|
@@ -228,5 +228,5 @@ var ProductCard = memo(function ProductCard2(props) {
|
|
|
228
228
|
});
|
|
229
229
|
|
|
230
230
|
export { ProductCard };
|
|
231
|
-
//# sourceMappingURL=chunk-
|
|
232
|
-
//# sourceMappingURL=chunk-
|
|
231
|
+
//# sourceMappingURL=chunk-DYSSY56M.js.map
|
|
232
|
+
//# sourceMappingURL=chunk-DYSSY56M.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/product/ProductCard.tsx"],"names":["ProductCardContent","ProductCard"],"mappings":"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","file":"chunk-45UU2OKF.js","sourcesContent":["import { memo, useCallback, useMemo } from 'react';\nimport { SallaAddProductButton } from '@salla.sa/twilight-components-react/add-product-button';\nimport { SallaButton } from '@salla.sa/twilight-components-react/button';\nimport { useHostAttributes } from '@salla.sa/twilight-theme-engine/hooks/useHostAttributes';\nimport { useMoney } from '../../hooks/useMoney';\nimport { useTranslation } from '../../providers/I18nProvider';\nimport { useTwilight } from '../../providers/TwilightProvider';\nimport { useWishlist } from '../../hooks/useWishlist';\nimport { useAsset } from '../../hooks/useAsset';\nimport { useNumber } from '../../hooks/useNumber';\nimport { registry } from '../ComponentRegistry';\nimport { Image } from '../common';\nimport type { Product } from '../../types';\n\nconst PRODUCT_CARD_KEY = 'product:card';\n\nconst PRODUCT_IMAGE_SRCSET_WIDTHS = [150, 300, 450, 600] as const;\n/** Matches `.s-products-list-vertical-cards`: 2-col below 768px, 4-col above. */\nconst PRODUCT_IMAGE_SIZES = '(min-width: 768px) 25vw, 50vw';\n/** fullImage / minimal slots in FeaturedProductsStyle3 (`lg:grid-cols-2`). */\nconst PRODUCT_WIDE_IMAGE_SIZES = '(min-width: 1024px) 50vw, 100vw';\n\n/** Product card layout variants - mutually exclusive */\nexport type ProductCardLayout = 'vertical' | 'horizontal' | 'fullImage' | 'minimal' | 'special';\n\nexport interface ProductCardProps {\n product: Product;\n layout?: ProductCardLayout;\n className?: string;\n withShadow?: boolean;\n withQuantity?: boolean;\n withoutAddButton?: boolean;\n index?: number;\n imagePriority?: boolean;\n /** Overrides the layout-based image `sizes` hint. */\n sizes?: string;\n}\n\n/**\n * ProductCard - Displays a product in various layouts\n *\n * Layouts:\n * - vertical: Default card with image top, content bottom\n * - horizontal: Side-by-side image and content\n * - fullImage: Full bleed image with overlay content\n * - minimal: Compact version with reduced info\n * - special: Featured card with quantity pie chart\n *\n * Features:\n * - Native lazy loading for images\n * - Product badges (promotion, preorder, quantity, out of stock)\n * - Wishlist toggle button\n * - Price display (sale, starting, regular)\n * - Rating display\n * - Add to cart button via SallaAddProductButton (handles labels internally)\n */\nconst ProductCardContent = memo(function ProductCardContent({\n product,\n layout = 'vertical',\n className = '',\n withShadow = false,\n withQuantity = false,\n withoutAddButton = false,\n index = 0,\n imagePriority = false,\n sizes,\n}: ProductCardProps) {\n const { format } = useMoney();\n const { t } = useTranslation();\n const { store, theme } = useTwilight();\n const wishlist = useWishlist();\n const { isPlaceholder } = useAsset();\n const { format: formatNumber } = useNumber();\n\n // Out-of-stock cards offer \"notify me when available\" instead of a dead button, unless\n // the merchant switched `notify_when_available_in_card` off (Twig theme-raed parity).\n const notifyInCard = theme?.settings?.notify_when_available_in_card !== false;\n const addButtonStatus =\n notifyInCard &&\n product.is_out_of_stock &&\n product.type !== 'donating' &&\n product.type !== 'financial_support'\n ? 'out-and-notify'\n : product.status;\n\n const addButtonRef = useHostAttributes({ fill: 'outline', width: 'wide' });\n\n // Layout flags\n const isVertical = layout === 'vertical';\n const isHorizontal = layout === 'horizontal';\n const isFullImage = layout === 'fullImage';\n const isMinimal = layout === 'minimal';\n const isSpecial = layout === 'special';\n\n // Wishlist status\n const productInWishlist = wishlist.has(Number(product.id));\n const handleWishlistToggle = useCallback(() => {\n wishlist.toggle(Number(product.id));\n }, [wishlist, product.id]);\n\n // Get image fit type from store settings\n const fitImageHeight = store?.settings?.product?.fit_type;\n\n // Product badge component\n const getProductBadge = () => {\n if (product?.preorder?.label && typeof product.preorder.label === 'string') {\n return <div className=\"s-product-card-promotion-title\">{product.preorder.label}</div>;\n }\n if (product.promotion_title) {\n return <div className=\"s-product-card-promotion-title\">{product.promotion_title}</div>;\n }\n if (withQuantity && product?.quantity) {\n const formattedQty = formatNumber(product.quantity);\n return (\n <div className=\"s-product-card-quantity\">\n {t('pages.products.remained', 'Remained')} {formattedQty}\n </div>\n );\n }\n if (withQuantity && product?.is_out_of_stock) {\n return (\n <div className=\"s-product-card-out-badge\">\n {t('pages.products.out_of_stock', 'Out of Stock')}\n </div>\n );\n }\n return null;\n };\n\n // Price display component\n const getProductPrice = () => {\n if (product.is_on_sale && product.sale_price) {\n return (\n <div className=\"s-product-card-sale-price\">\n <h4>{format(product.sale_price)}</h4>\n {product.regular_price && <span>{format(product.regular_price)}</span>}\n </div>\n );\n }\n if (product.starting_price) {\n return (\n <div className=\"s-product-card-starting-price\">\n <p>{t('pages.products.starting_price', 'Starting from')}</p>\n <h4>{format(product.starting_price)}</h4>\n </div>\n );\n }\n return <h4 className=\"s-product-card-price\">{format(product.price)}</h4>;\n };\n\n // Build card class names\n const cardClassName = [\n 's-product-card',\n 's-product-card-entry',\n isVertical ? 's-product-card-vertical' : '',\n isHorizontal ? 's-product-card-horizontal' : '',\n fitImageHeight && isVertical ? `s-product-card-fit-height` : '',\n isSpecial ? 's-product-card-special' : '',\n isFullImage ? 's-product-card-full-image' : '',\n isMinimal ? 's-product-card-minimal' : '',\n product?.donation ? 's-product-card-donation' : '',\n withShadow ? 's-product-card-shadow' : '',\n product?.is_out_of_stock ? 's-product-card-out-of-stock' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n // Image fit class\n const isProductPlaceholder = isPlaceholder(product.image?.url);\n const imageFitClass = isProductPlaceholder ? 'contain' : fitImageHeight || 'cover';\n\n return (\n <div\n id={`product-card-${product.id}`}\n className={cardClassName}\n data-product-id={product.id}\n style={{\n animationDelay: `${index * 100}ms`,\n }}\n >\n <div className={isFullImage ? 's-product-card-image-full' : 's-product-card-image'}>\n <a href={product.url} aria-label={product.image?.alt || product.name}>\n <Image\n className={`s-product-card-image-${imageFitClass}`}\n src={product.image?.url}\n alt={product.image?.alt ?? product.name}\n width={300}\n height={300}\n sizes={\n sizes ?? (isFullImage || isMinimal ? PRODUCT_WIDE_IMAGE_SIZES : PRODUCT_IMAGE_SIZES)\n }\n srcSetWidths={PRODUCT_IMAGE_SRCSET_WIDTHS}\n aspectRatio=\"1/1\"\n priority={imagePriority}\n />\n {!isFullImage && !isMinimal && getProductBadge()}\n </a>\n {isFullImage && (\n <a href={product.url} aria-label={product.name} className=\"s-product-card-overlay\" />\n )}\n {!isHorizontal && !isFullImage && (\n <SallaButton\n shape=\"icon\"\n fill=\"outline\"\n color=\"light\"\n ariaLabel={t('pages.wishlist.toggle', 'Add or remove to wishlist')}\n className={`s-product-card-wishlist-btn animated ${productInWishlist ? 's-product-card-wishlist-added pulse-anime' : 'not-added un-favorited'}`}\n onClick={handleWishlistToggle}\n data-id={product.id}\n >\n <i className=\"sicon-heart\" />\n </SallaButton>\n )}\n </div>\n <div className=\"s-product-card-content\">\n {/* Special card: quantity pie */}\n {isSpecial && product?.quantity && (\n <div className=\"s-product-card-content-pie\">\n <span>\n <b>{formatNumber(product.quantity)}</b>\n {t('pages.products.remained', 'Remained')}\n </span>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"-2 -1 36 34\"\n className=\"s-product-card-content-pie-svg\"\n >\n <circle cx=\"16\" cy=\"16\" r=\"15.9155\" className=\"s-product-card-content-pie-svg-base\" />\n <circle cx=\"16\" cy=\"16\" r=\"15.9155\" className=\"s-product-card-content-pie-svg-bar\" />\n </svg>\n </div>\n )}\n\n <div\n className={`s-product-card-content-main ${isSpecial ? 's-product-card-content-extra-padding' : ''}`}\n >\n <h3 className=\"s-product-card-content-title\">\n <a href={product.url}>{product.name}</a>\n </h3>\n {product.subtitle && !isMinimal && (\n <p className=\"s-product-card-content-subtitle opacity-80\">{product.subtitle}</p>\n )}\n </div>\n\n <div\n className={`s-product-card-content-sub ${isSpecial ? 's-product-card-content-extra-padding' : ''}`}\n >\n {!product?.donation?.can_donate && getProductPrice()}\n {product.rating?.stars && (\n <div className=\"s-product-card-rating\">\n <i className=\"sicon-star2 text-orange-300\" />\n <span>{product.rating.stars}</span>\n </div>\n )}\n </div>\n\n {!withoutAddButton && (\n <div className=\"s-product-card-content-footer gap-2\">\n <SallaAddProductButton\n ref={addButtonRef}\n fill=\"outline\"\n width=\"wide\"\n productId={product.id}\n productStatus={addButtonStatus}\n productType={product.type}\n hasPreOrder={product.has_preorder_campaign}\n />\n {(isHorizontal || isFullImage) && (\n <SallaButton\n shape=\"icon\"\n fill=\"outline\"\n color=\"light\"\n ariaLabel={t('pages.wishlist.toggle', 'Add or remove to wishlist')}\n className={`s-product-card-wishlist-btn animated ${productInWishlist ? 's-product-card-wishlist-added pulse-anime' : 'not-added un-favorited'}`}\n onClick={handleWishlistToggle}\n data-id={product.id}\n >\n <i className=\"sicon-heart\" />\n </SallaButton>\n )}\n </div>\n )}\n </div>\n </div>\n );\n});\n\nexport const ProductCard = memo(function ProductCard(props: ProductCardProps) {\n const Component = useMemo(() => {\n const hasOverride = registry.getOriginal<ProductCardProps>(PRODUCT_CARD_KEY) !== null;\n if (hasOverride) {\n return registry.resolve<ProductCardProps>(PRODUCT_CARD_KEY);\n }\n return null;\n }, []);\n\n if (Component) {\n return <Component {...props} />;\n }\n\n return <ProductCardContent {...props} />;\n});\n\nexport default ProductCard;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/product/ProductCard.tsx"],"names":["ProductCardContent","ProductCard"],"mappings":"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","file":"chunk-DYSSY56M.js","sourcesContent":["import { memo, useCallback, useMemo } from 'react';\nimport { SallaAddProductButton } from '@salla.sa/twilight-components-react/add-product-button';\nimport { SallaButton } from '@salla.sa/twilight-components-react/button';\nimport { useHostAttributes } from '@salla.sa/twilight-theme-engine/hooks/useHostAttributes';\nimport { useMoney } from '../../hooks/useMoney';\nimport { useTranslation } from '../../providers/I18nProvider';\nimport { useTwilight } from '../../providers/TwilightProvider';\nimport { useWishlist } from '../../hooks/useWishlist';\nimport { useAsset } from '../../hooks/useAsset';\nimport { useNumber } from '../../hooks/useNumber';\nimport { registry } from '../ComponentRegistry';\nimport { Image } from '../common';\nimport type { Product } from '../../types';\n\nconst PRODUCT_CARD_KEY = 'product:card';\n\nconst PRODUCT_IMAGE_SRCSET_WIDTHS = [150, 300, 450, 600] as const;\n/** Matches `.s-products-list-vertical-cards`: 2-col below 768px, 4-col above. */\nconst PRODUCT_IMAGE_SIZES = '(min-width: 768px) 25vw, 50vw';\n/** fullImage / minimal slots in FeaturedProductsStyle3 (`lg:grid-cols-2`). */\nconst PRODUCT_WIDE_IMAGE_SIZES = '(min-width: 1024px) 50vw, 100vw';\n\n/** Product card layout variants - mutually exclusive */\nexport type ProductCardLayout = 'vertical' | 'horizontal' | 'fullImage' | 'minimal' | 'special';\n\nexport interface ProductCardProps {\n product: Product;\n layout?: ProductCardLayout;\n className?: string;\n withShadow?: boolean;\n withQuantity?: boolean;\n withoutAddButton?: boolean;\n index?: number;\n imagePriority?: boolean;\n /** Overrides the layout-based image `sizes` hint. */\n sizes?: string;\n}\n\n/**\n * ProductCard - Displays a product in various layouts\n *\n * Layouts:\n * - vertical: Default card with image top, content bottom\n * - horizontal: Side-by-side image and content\n * - fullImage: Full bleed image with overlay content\n * - minimal: Compact version with reduced info\n * - special: Featured card with quantity pie chart\n *\n * Features:\n * - Native lazy loading for images\n * - Product badges (promotion, preorder, quantity, out of stock)\n * - Wishlist toggle button\n * - Price display (sale, starting, regular)\n * - Rating display\n * - Add to cart button via SallaAddProductButton (handles labels internally)\n */\nconst ProductCardContent = memo(function ProductCardContent({\n product,\n layout = 'vertical',\n className = '',\n withShadow = false,\n withQuantity = false,\n withoutAddButton = false,\n index = 0,\n imagePriority = false,\n sizes,\n}: ProductCardProps) {\n const { format } = useMoney();\n const { t } = useTranslation();\n const { store, theme } = useTwilight();\n const wishlist = useWishlist();\n const { isPlaceholder } = useAsset();\n const { format: formatNumber } = useNumber();\n\n // Out-of-stock cards offer \"notify me when available\" instead of a dead button, unless\n // the merchant switched `notify_when_available_in_card` off (Twig theme-raed parity).\n const notifyInCard = theme?.settings?.notify_when_available_in_card !== false;\n const addButtonStatus =\n notifyInCard &&\n product.is_out_of_stock &&\n product.type !== 'donating' &&\n product.type !== 'financial_support'\n ? 'out-and-notify'\n : product.status;\n\n const addButtonRef = useHostAttributes({ fill: 'outline', width: 'wide' });\n\n // Layout flags\n const isVertical = layout === 'vertical';\n const isHorizontal = layout === 'horizontal';\n const isFullImage = layout === 'fullImage';\n const isMinimal = layout === 'minimal';\n const isSpecial = layout === 'special';\n\n // Wishlist status\n const productInWishlist = wishlist.has(Number(product.id));\n const handleWishlistToggle = useCallback(() => {\n wishlist.toggle(Number(product.id));\n }, [wishlist, product.id]);\n\n // Get image fit type from store settings\n const fitImageHeight = store?.settings?.product?.fit_type;\n\n // Product badge component\n const getProductBadge = () => {\n if (product?.preorder?.label && typeof product.preorder.label === 'string') {\n return <div className=\"s-product-card-promotion-title\">{product.preorder.label}</div>;\n }\n if (product.promotion_title) {\n return <div className=\"s-product-card-promotion-title\">{product.promotion_title}</div>;\n }\n if (withQuantity && product?.quantity) {\n const formattedQty = formatNumber(product.quantity);\n return (\n <div className=\"s-product-card-quantity\">\n {t('pages.products.remained', 'Remained')} {formattedQty}\n </div>\n );\n }\n if (withQuantity && product?.is_out_of_stock) {\n return (\n <div className=\"s-product-card-out-badge\">\n {t('pages.products.out_of_stock', 'Out of Stock')}\n </div>\n );\n }\n return null;\n };\n\n // Price display component\n const getProductPrice = () => {\n if (product.is_on_sale && product.sale_price) {\n return (\n <div className=\"s-product-card-sale-price\">\n <h4>{format(product.sale_price)}</h4>\n {product.regular_price && <span>{format(product.regular_price)}</span>}\n </div>\n );\n }\n if (product.starting_price) {\n return (\n <div className=\"s-product-card-starting-price\">\n <p>{t('pages.products.starting_price', 'Starting from')}</p>\n <h4>{format(product.starting_price)}</h4>\n </div>\n );\n }\n return <h4 className=\"s-product-card-price\">{format(product.price)}</h4>;\n };\n\n // Build card class names\n const cardClassName = [\n 's-product-card',\n 's-product-card-entry',\n isVertical ? 's-product-card-vertical' : '',\n isHorizontal ? 's-product-card-horizontal' : '',\n fitImageHeight && isVertical ? `s-product-card-fit-height` : '',\n isSpecial ? 's-product-card-special' : '',\n isFullImage ? 's-product-card-full-image' : '',\n isMinimal ? 's-product-card-minimal' : '',\n product?.donation ? 's-product-card-donation' : '',\n withShadow ? 's-product-card-shadow' : '',\n product?.is_out_of_stock ? 's-product-card-out-of-stock' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n // Image fit class\n const isProductPlaceholder = isPlaceholder(product.image?.url);\n const imageFitClass = isProductPlaceholder ? 'contain' : fitImageHeight || 'cover';\n\n return (\n <div\n id={`product-card-${product.id}`}\n className={cardClassName}\n data-product-id={product.id}\n style={{\n animationDelay: `${index * 100}ms`,\n }}\n >\n <div className={isFullImage ? 's-product-card-image-full' : 's-product-card-image'}>\n <a href={product.url} aria-label={product.image?.alt || product.name}>\n <Image\n className={`s-product-card-image-${imageFitClass}`}\n src={product.image?.url}\n alt={product.image?.alt ?? product.name}\n width={300}\n height={300}\n sizes={\n sizes ?? (isFullImage || isMinimal ? PRODUCT_WIDE_IMAGE_SIZES : PRODUCT_IMAGE_SIZES)\n }\n srcSetWidths={PRODUCT_IMAGE_SRCSET_WIDTHS}\n aspectRatio=\"1/1\"\n priority={imagePriority}\n />\n {!isFullImage && !isMinimal && getProductBadge()}\n </a>\n {isFullImage && (\n <a href={product.url} aria-label={product.name} className=\"s-product-card-overlay\" />\n )}\n {!isHorizontal && !isFullImage && (\n <SallaButton\n shape=\"icon\"\n fill=\"outline\"\n color=\"light\"\n ariaLabel={t('pages.wishlist.toggle', 'Add or remove to wishlist')}\n className={`s-product-card-wishlist-btn animated ${productInWishlist ? 's-product-card-wishlist-added pulse-anime' : 'not-added un-favorited'}`}\n onClick={handleWishlistToggle}\n data-id={product.id}\n >\n <i className=\"sicon-heart\" />\n </SallaButton>\n )}\n </div>\n <div className=\"s-product-card-content\">\n {/* Special card: quantity pie */}\n {isSpecial && product?.quantity && (\n <div className=\"s-product-card-content-pie\">\n <span>\n <b>{formatNumber(product.quantity)}</b>\n {t('pages.products.remained', 'Remained')}\n </span>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"-2 -1 36 34\"\n className=\"s-product-card-content-pie-svg\"\n >\n <circle cx=\"16\" cy=\"16\" r=\"15.9155\" className=\"s-product-card-content-pie-svg-base\" />\n <circle cx=\"16\" cy=\"16\" r=\"15.9155\" className=\"s-product-card-content-pie-svg-bar\" />\n </svg>\n </div>\n )}\n\n <div\n className={`s-product-card-content-main ${isSpecial ? 's-product-card-content-extra-padding' : ''}`}\n >\n <h3 className=\"s-product-card-content-title\">\n <a href={product.url}>{product.name}</a>\n </h3>\n {product.subtitle && !isMinimal && (\n <p className=\"s-product-card-content-subtitle opacity-80\">{product.subtitle}</p>\n )}\n </div>\n\n <div\n className={`s-product-card-content-sub ${isSpecial ? 's-product-card-content-extra-padding' : ''}`}\n >\n {!product?.donation?.can_donate && getProductPrice()}\n {product.rating?.stars && (\n <div className=\"s-product-card-rating\">\n <i className=\"sicon-star2 text-orange-300\" />\n <span>{product.rating.stars}</span>\n </div>\n )}\n </div>\n\n {!withoutAddButton && (\n <div className=\"s-product-card-content-footer gap-2\">\n <SallaAddProductButton\n ref={addButtonRef}\n fill=\"outline\"\n width=\"wide\"\n productId={product.id}\n productStatus={addButtonStatus}\n productType={product.type}\n hasPreOrder={product.has_preorder_campaign}\n />\n {(isHorizontal || isFullImage) && (\n <SallaButton\n shape=\"icon\"\n fill=\"outline\"\n color=\"light\"\n ariaLabel={t('pages.wishlist.toggle', 'Add or remove to wishlist')}\n className={`s-product-card-wishlist-btn animated ${productInWishlist ? 's-product-card-wishlist-added pulse-anime' : 'not-added un-favorited'}`}\n onClick={handleWishlistToggle}\n data-id={product.id}\n >\n <i className=\"sicon-heart\" />\n </SallaButton>\n )}\n </div>\n )}\n </div>\n </div>\n );\n});\n\nexport const ProductCard = memo(function ProductCard(props: ProductCardProps) {\n const Component = useMemo(() => {\n const hasOverride = registry.getOriginal<ProductCardProps>(PRODUCT_CARD_KEY) !== null;\n if (hasOverride) {\n return registry.resolve<ProductCardProps>(PRODUCT_CARD_KEY);\n }\n return null;\n }, []);\n\n if (Component) {\n return <Component {...props} />;\n }\n\n return <ProductCardContent {...props} />;\n});\n\nexport default ProductCard;\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { redirect } from './chunk-
|
|
1
|
+
import { redirect } from './chunk-OPON37ZR.js';
|
|
2
2
|
import { clearAuthTokenCookie } from './chunk-FXVII733.js';
|
|
3
3
|
import { FALLBACK_LOCALE } from './chunk-T72DAX7R.js';
|
|
4
4
|
import { useEffect } from 'react';
|
|
@@ -37,5 +37,5 @@ function LogoutRedirect() {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
export { LogoutRedirect, accountRedirectLoader, pendingOrdersRedirectLoader, productsSourceRedirectLoader, ratingRedirectLoader, slugBrandRedirectLoader };
|
|
40
|
-
//# sourceMappingURL=chunk-
|
|
41
|
-
//# sourceMappingURL=chunk-
|
|
40
|
+
//# sourceMappingURL=chunk-FH4EVOMN.js.map
|
|
41
|
+
//# sourceMappingURL=chunk-FH4EVOMN.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/routes/seo-redirects.ts"],"names":[],"mappings":";;;;;AAcA,eAAsB,wBAAwB,GAAA,EAAkD;AAC9F,EAAA,MAAM,MAAA,GAAS,GAAA,CAAI,MAAA,CAAO,MAAA,IAAU,eAAA;AACpC,EAAA,MAAM,SAAS,CAAA,CAAA,EAAI,MAAM,WAAW,GAAA,CAAI,MAAA,CAAO,EAAE,CAAA,CAAE,CAAA;AACrD;AAOA,eAAsB,4BACpB,GAAA,GAA+C,EAAE,MAAA,EAAQ,IAAG,EAC5C;AAChB,EAAA,MAAM,MAAA,GAAS,GAAA,CAAI,MAAA,CAAO,MAAA,IAAU,eAAA;AACpC,EAAA,MAAM,QAAA,CAAS,CAAA,CAAA,EAAI,MAAM,CAAA,8BAAA,CAAgC,CAAA;AAC3D;AAGA,eAAsB,qBACpB,GAAA,GAA+C,EAAE,MAAA,EAAQ,IAAG,EAC5C;AAChB,EAAA,MAAM,MAAA,GAAS,GAAA,CAAI,MAAA,CAAO,MAAA,IAAU,eAAA;AACpC,EAAA,MAAM,QAAA,CAAS,CAAA,CAAA,EAAI,MAAM,CAAA,eAAA,CAAiB,CAAA;AAC5C;AAGA,eAAsB,sBAAsB,GAAA,EAKzB;AAEjB,EAAA,MAAM,MAAA,GAAS,IAAI,MAAA,CAAO,MAAA,GAAS,IAAI,GAAA,CAAI,MAAA,CAAO,MAAM,CAAA,CAAA,GAAK,EAAA;AAC7D,EAAA,MAAM,QAAA,CAAS,CAAA,EAAG,MAAM,CAAA,SAAA,EAAY,IAAI,IAAI,CAAA,EAAG,GAAA,CAAI,MAAA,IAAU,EAAE,CAAA,CAAA,EAAI,EAAE,UAAA,EAAY,KAAK,CAAA;AACxF;AAGA,eAAsB,6BAA6B,GAAA,EAIhC;AACjB,EAAA,MAAM,MAAA,GAAS,IAAI,MAAA,CAAO,MAAA,GAAS,IAAI,GAAA,CAAI,MAAA,CAAO,MAAM,CAAA,CAAA,GAAK,EAAA;AAC7D,EAAA,MAAM,KAAA,GAAQ,IAAI,eAAA,CAAgB,GAAA,CAAI,MAAM,CAAA;AAC5C,EAAA,KAAA,CAAM,OAAO,QAAQ,CAAA;AACrB,EAAA,MAAM,IAAA,GAAO,MAAM,QAAA,EAAS;AAC5B,EAAA,MAAM,QAAA,CAAS,CAAA,EAAG,MAAM,CAAA,iBAAA,EAAoB,GAAA,CAAI,MAAM,CAAA,EAAG,IAAA,GAAO,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,GAAK,EAAE,CAAA,CAAA,EAAI;AAAA,IACjF,UAAA,EAAY;AAAA,GACb,CAAA;AACH;AAUO,SAAS,cAAA,GAAuB;AACrC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,oBAAA,EAAqB;AAErB,IAAA,MAAA,CAAO,QAAA,CAAS,QAAQ,MAAA,CAAO,QAAA,CAAS,KAAK,OAAA,CAAQ,8BAAA,EAAgC,EAAE,CAAC,CAAA;AAAA,EAC1F,CAAA,EAAG,EAAE,CAAA;AACL,EAAA,OAAO,IAAA;AACT","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/routes/seo-redirects.ts"],"names":[],"mappings":";;;;;AAcA,eAAsB,wBAAwB,GAAA,EAAkD;AAC9F,EAAA,MAAM,MAAA,GAAS,GAAA,CAAI,MAAA,CAAO,MAAA,IAAU,eAAA;AACpC,EAAA,MAAM,SAAS,CAAA,CAAA,EAAI,MAAM,WAAW,GAAA,CAAI,MAAA,CAAO,EAAE,CAAA,CAAE,CAAA;AACrD;AAOA,eAAsB,4BACpB,GAAA,GAA+C,EAAE,MAAA,EAAQ,IAAG,EAC5C;AAChB,EAAA,MAAM,MAAA,GAAS,GAAA,CAAI,MAAA,CAAO,MAAA,IAAU,eAAA;AACpC,EAAA,MAAM,QAAA,CAAS,CAAA,CAAA,EAAI,MAAM,CAAA,8BAAA,CAAgC,CAAA;AAC3D;AAGA,eAAsB,qBACpB,GAAA,GAA+C,EAAE,MAAA,EAAQ,IAAG,EAC5C;AAChB,EAAA,MAAM,MAAA,GAAS,GAAA,CAAI,MAAA,CAAO,MAAA,IAAU,eAAA;AACpC,EAAA,MAAM,QAAA,CAAS,CAAA,CAAA,EAAI,MAAM,CAAA,eAAA,CAAiB,CAAA;AAC5C;AAGA,eAAsB,sBAAsB,GAAA,EAKzB;AAEjB,EAAA,MAAM,MAAA,GAAS,IAAI,MAAA,CAAO,MAAA,GAAS,IAAI,GAAA,CAAI,MAAA,CAAO,MAAM,CAAA,CAAA,GAAK,EAAA;AAC7D,EAAA,MAAM,QAAA,CAAS,CAAA,EAAG,MAAM,CAAA,SAAA,EAAY,IAAI,IAAI,CAAA,EAAG,GAAA,CAAI,MAAA,IAAU,EAAE,CAAA,CAAA,EAAI,EAAE,UAAA,EAAY,KAAK,CAAA;AACxF;AAGA,eAAsB,6BAA6B,GAAA,EAIhC;AACjB,EAAA,MAAM,MAAA,GAAS,IAAI,MAAA,CAAO,MAAA,GAAS,IAAI,GAAA,CAAI,MAAA,CAAO,MAAM,CAAA,CAAA,GAAK,EAAA;AAC7D,EAAA,MAAM,KAAA,GAAQ,IAAI,eAAA,CAAgB,GAAA,CAAI,MAAM,CAAA;AAC5C,EAAA,KAAA,CAAM,OAAO,QAAQ,CAAA;AACrB,EAAA,MAAM,IAAA,GAAO,MAAM,QAAA,EAAS;AAC5B,EAAA,MAAM,QAAA,CAAS,CAAA,EAAG,MAAM,CAAA,iBAAA,EAAoB,GAAA,CAAI,MAAM,CAAA,EAAG,IAAA,GAAO,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,GAAK,EAAE,CAAA,CAAA,EAAI;AAAA,IACjF,UAAA,EAAY;AAAA,GACb,CAAA;AACH;AAUO,SAAS,cAAA,GAAuB;AACrC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,oBAAA,EAAqB;AAErB,IAAA,MAAA,CAAO,QAAA,CAAS,QAAQ,MAAA,CAAO,QAAA,CAAS,KAAK,OAAA,CAAQ,8BAAA,EAAgC,EAAE,CAAC,CAAA;AAAA,EAC1F,CAAA,EAAG,EAAE,CAAA;AACL,EAAA,OAAO,IAAA;AACT","file":"chunk-FH4EVOMN.js","sourcesContent":["import { useEffect } from 'react';\nimport { redirect } from '../providers/NavigationProvider';\nimport { FALLBACK_LOCALE } from '../providers/locale-constants';\nimport { clearAuthTokenCookie } from '../utils/cookies';\n\nexport interface SlugBrandParams {\n /** SEO slug segment (ignored — only here to match the route pattern). */\n slug: string;\n /** Brand numeric ID to redirect to. */\n id: string;\n /** Active locale from the `/$locale` parent layout (e.g. `'ar'`, `'en'`). */\n locale?: string;\n}\n\nexport async function slugBrandRedirectLoader(ctx: { params: SlugBrandParams }): Promise<never> {\n const locale = ctx.params.locale || FALLBACK_LOCALE;\n throw redirect(`/${locale}/brands/${ctx.params.id}`);\n}\n\nexport interface PendingOrdersRedirectParams {\n /** Active locale from the `/$locale` parent layout (e.g. `'ar'`, `'en'`). */\n locale?: string;\n}\n\nexport async function pendingOrdersRedirectLoader(\n ctx: { params: PendingOrdersRedirectParams } = { params: {} }\n): Promise<never> {\n const locale = ctx.params.locale || FALLBACK_LOCALE;\n throw redirect(`/${locale}/account/orders?status=pending`);\n}\n\n/** `/account/rating`: the loyalty \"rate your orders\" link. Twig Raed has no rating page and sends it to the orders list. */\nexport async function ratingRedirectLoader(\n ctx: { params: PendingOrdersRedirectParams } = { params: {} }\n): Promise<never> {\n const locale = ctx.params.locale || FALLBACK_LOCALE;\n throw redirect(`/${locale}/account/orders`);\n}\n\n/** A Twig customer URL (`/profile`, `/orders`, …) kept working as its `/account/…` page. */\nexport async function accountRedirectLoader(ctx: {\n params: PendingOrdersRedirectParams;\n page: string;\n /** The incoming query string (`?status=pending`), kept on the account page. */\n search?: string;\n}): Promise<never> {\n // No locale in the URL stays without one: the locale layout adds it only where the store has several.\n const prefix = ctx.params.locale ? `/${ctx.params.locale}` : '';\n throw redirect(`${prefix}/account/${ctx.page}${ctx.search ?? ''}`, { statusCode: 301 });\n}\n\n/** `/latest-products`, `/most-sales-products` and `/offers` now live at `/products?source=`. */\nexport async function productsSourceRedirectLoader(ctx: {\n params: PendingOrdersRedirectParams;\n source: 'latest' | 'sales' | 'offers';\n search?: string;\n}): Promise<never> {\n const prefix = ctx.params.locale ? `/${ctx.params.locale}` : '';\n const query = new URLSearchParams(ctx.search);\n query.delete('source');\n const rest = query.toString();\n throw redirect(`${prefix}/products?source=${ctx.source}${rest ? `&${rest}` : ''}`, {\n statusCode: 301,\n });\n}\n\n/**\n * `/logout` — where the SDK sends the browser once `salla.auth.logout()` has run\n * (`salla.url.get('logout?from=…')`). The Twig storefront serves that URL server-side. Here\n * it renders nothing and, in the browser, removes the theme's own `token` cookie (the SDK's\n * `cookie.clearAll()` leaves it) and then does a full navigation home. It has to be a\n * component, not a loader redirect: a loader runs during server rendering, where the cookie\n * can't be cleared, so the redirect would leave the visitor signed in on the next request.\n */\nexport function LogoutRedirect(): null {\n useEffect(() => {\n clearAuthTokenCookie();\n // `/{store base}/{locale}/logout?from=…` → `/{store base}/{locale}`\n window.location.replace(window.location.href.replace(/\\/logout\\/?(\\?[^#]*)?(#.*)?$/, ''));\n }, []);\n return null;\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isNotLaunchedNotice } from './chunk-Q7E4TNN7.js';
|
|
2
|
-
import { getActiveScope, api, STORE_IDENTIFIER_HEADER, devSettingsFetchedAt } from './chunk-
|
|
2
|
+
import { getActiveScope, api, STORE_IDENTIFIER_HEADER, devSettingsFetchedAt } from './chunk-WDL6T5RX.js';
|
|
3
3
|
import { requestedThemeVersionId } from './chunk-NHA4SBKG.js';
|
|
4
4
|
import { LANGUAGE_COOKIE_NAME, LANGUAGE_COOKIE_MAX_AGE, resolveStoreIdentifier, extractScopeFromUrl, parseStoreId } from './chunk-FXVII733.js';
|
|
5
5
|
import { getTwilightContext, SettingsError } from './chunk-6K34BCUP.js';
|
|
@@ -250,5 +250,5 @@ var store = {
|
|
|
250
250
|
};
|
|
251
251
|
|
|
252
252
|
export { persistLanguageCookie, readCookieHeader, readNativeAppHeaders, readPageSearch, store };
|
|
253
|
-
//# sourceMappingURL=chunk-
|
|
254
|
-
//# sourceMappingURL=chunk-
|
|
253
|
+
//# sourceMappingURL=chunk-GDLT2GGX.js.map
|
|
254
|
+
//# sourceMappingURL=chunk-GDLT2GGX.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/language-cookie.ts","../src/utils/native-app-headers.ts","../src/api/store.ts"],"names":[],"mappings":"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","file":"chunk-IS6CEQF7.js","sourcesContent":["/**\n * @fileoverview Reading and writing the `s-lang` cookie, on the server and in the browser.\n *\n * The server reads it from the request the framework is handling and writes it to that\n * request's response. The server-only import is stripped from the client bundle by\n * `createIsomorphicFn`, as in `routes/root/beforeLoad.ts`. The browser uses `document.cookie`.\n * Either side outside a request (a prerender, a test) has nothing to read or write and says so\n * quietly.\n */\nimport { createIsomorphicFn } from '@tanstack/react-start';\nimport { getRequestHeader, getRequestUrl, setCookie } from '@tanstack/react-start/server';\nimport { LANGUAGE_COOKIE_MAX_AGE, LANGUAGE_COOKIE_NAME } from './cookies';\n\nconst readServerCookieHeader = createIsomorphicFn()\n .server((): string | null => {\n try {\n return getRequestHeader('cookie') ?? null;\n } catch {\n return null;\n }\n })\n .client((): string | null => null);\n\nconst writeServerLanguageCookie = createIsomorphicFn()\n .server((code: string): void => {\n try {\n setCookie(LANGUAGE_COOKIE_NAME, code, {\n path: '/',\n maxAge: LANGUAGE_COOKIE_MAX_AGE,\n sameSite: 'lax',\n });\n } catch {\n // Outside a request: there is no response to write to.\n }\n })\n .client((): void => {});\n\nconst readServerSearch = createIsomorphicFn()\n .server((): string => {\n try {\n return getRequestUrl().search;\n } catch {\n return '';\n }\n })\n .client((): string => '');\n\n/**\n * The query string of the page being rendered (`?lang=en`, or `''`): the request's on the\n * server, the address bar's in the browser, so both sides read the same one.\n */\nexport function readPageSearch(): string {\n return readServerSearch() || (typeof window !== 'undefined' ? window.location.search : '');\n}\n\n/** The `Cookie` header of the request being handled, or `document.cookie` in the browser. */\nexport function readCookieHeader(): string | null {\n return readServerCookieHeader() ?? (typeof document !== 'undefined' ? document.cookie : null);\n}\n\n/** Remembers `code` as the visitor's language for every store on this host. */\nexport function persistLanguageCookie(code: string): void {\n writeServerLanguageCookie(code);\n if (typeof document !== 'undefined') {\n document.cookie = `${LANGUAGE_COOKIE_NAME}=${encodeURIComponent(code)}; path=/; max-age=${LANGUAGE_COOKIE_MAX_AGE}; SameSite=Lax`;\n }\n}\n","/** The headers the Salla native app sends with every page it loads in its webview. */\nexport const NATIVE_APP_HEADERS = [\n 's-app-os',\n 's-app-version',\n 's-app-full-version',\n 's-app-os-version',\n];\n\n/**\n * The native app's own headers on this request, or null when it is not the app.\n *\n * On a Twig theme Laravel copies them into the settings' `jitsu.context.extra.headers`,\n * where the SDK reads the app's platform and version from (`salla.config.isMobileApp()`).\n * A React theme asks for its settings from the server, through the API, so the app's\n * headers never reach that call: the request is the only place they are.\n */\nexport function readNativeAppHeaders(headers: Headers): Record<string, string> | null {\n const os = headers.get('s-app-os')?.toLowerCase();\n if (os !== 'ios' && os !== 'android') return null;\n const found: Record<string, string> = {};\n for (const name of NATIVE_APP_HEADERS) {\n const value = headers.get(name);\n if (value) found[name] = value;\n }\n return found;\n}\n","import { queryOptions } from '@tanstack/react-query';\nimport { isHTTPError, isNetworkError, isTimeoutError } from 'ky';\nimport { api, getActiveScope, STORE_IDENTIFIER_HEADER } from './client';\nimport { devSettingsFetchedAt } from './dev-settings-cache';\nimport { SettingsError } from '../utils/errors';\nimport type { Store, Theme, Language, JitsuConfig, MaintenanceDetails } from '../types';\nimport { getTwilightContext } from '../twilight/context';\nimport { resolveStoreIdentifier } from '../utils/store-identity';\nimport { extractScopeFromUrl, parseStoreId } from '../utils/cookies';\nimport { readPageSearch } from '../utils/language-cookie';\nimport { requestedThemeVersionId } from '../utils/theme-version';\nimport { NATIVE_APP_HEADERS } from '../utils/native-app-headers';\nimport { isNotLaunchedNotice } from '../utils/maintenance';\n\nexport { resolveStoreIdentifier };\n\nconst DEFAULT_INCLUDE_ITEMS = [\n 'store',\n 'settings',\n 'theme',\n 'theme_settings',\n 'external_services',\n 'currencies',\n 'languages',\n 'payments',\n 'product_widgets',\n 'rating',\n 'ratings',\n 'user',\n];\n\n/** Twig's `salla.init({ user })` object; the endpoint ignores the token, so always the guest. */\nexport interface SettingsUser {\n type: 'guest' | 'user';\n id?: number | string | null;\n language_code?: string;\n currency_code?: string;\n country_code?: string;\n [key: string]: unknown;\n}\n\n/**\n * Raw API response for settings endpoint.\n * Languages come as object: { \"AR\": { code, name, ... }, \"EN\": {...} }\n */\ninterface SettingsApiResponse {\n store?: Store;\n theme?: Theme;\n languages?: Record<string, Language>;\n currencies?: Record<\n string,\n { code: string; name: string; symbol: string; amount: number; country_code: string }\n >;\n external_services?: Record<string, unknown>;\n headers?: Record<string, unknown>;\n login?: { url: string; turnstile_site_key: string };\n affiliate?: { utm_url: string; cta_enabled: boolean };\n debug?: boolean;\n trace_console?: boolean;\n policy_url?: string;\n user?: SettingsUser;\n swoole?: string[];\n jitsu?: JitsuConfig;\n maintenance?: boolean;\n maintenance_details?: MaintenanceDetails;\n}\n\n/**\n * Central settings context - single source of truth for all API data.\n * Contains everything from the settings endpoint response after processing.\n */\nexport interface StoreContext {\n store?: Store;\n theme?: Theme;\n /** Languages as array after conversion from API object format */\n languages?: Language[];\n currencies?: Record<\n string,\n { code: string; name: string; symbol: string; amount: number; country_code: string }\n >;\n external_services?: Record<string, unknown>;\n headers?: Record<string, unknown>;\n login?: { url: string; turnstile_site_key: string };\n affiliate?: { utm_url: string; cta_enabled: boolean };\n debug?: boolean;\n trace_console?: boolean; // todo:: remove it\n policy_url?: string;\n user?: SettingsUser;\n /** API paths the SDK sends with `s-store-api-version: swoole` */\n swoole?: string[];\n /** Where the SDK's analytics send events, and which ones; without it the SDK tracks nothing. */\n jitsu?: JitsuConfig;\n /**\n * The store is closed: by the merchant from the dashboard, by the platform, or\n * for the selected market only. The engine then renders the maintenance page\n * to everyone but the merchant; see `rootBeforeLoad`.\n */\n maintenance?: boolean;\n /** What the maintenance page says; sent beside `maintenance`. */\n maintenance_details?: MaintenanceDetails;\n /**\n * `false` while the store has not launched yet: `maintenance` is then `true` and the\n * engine's maintenance page says the store is launching soon. Absent otherwise. Not\n * from the API: read off `maintenance_details` by `store.settings`, since the\n * backend sends the merchant's \"finish launching\" notice there for every visitor,\n * which is not for a customer's eyes.\n */\n launched?: false;\n /**\n * The scope these settings were requested with; absent when none was. Not from\n * the API: stamped by `store.settings`, so `resolveThemeVersionId` can tell\n * whether the version they name still answers the scope that is active now.\n */\n requestedScopeId?: string;\n /** Which answer of the API these settings are; see {@link SettingsAnswer}. */\n answer?: SettingsAnswer;\n /**\n * When the dev server fetched these settings from the API (epoch ms). It reuses\n * them for a while (see `dev-settings-cache.ts`) and the theme editor says how old\n * they are. Only on a dev server render; absent everywhere else.\n */\n devFetchedAt?: number;\n}\n\n/**\n * Which answer of the settings API a set of settings came from, read off the\n * response rather than the body: the API's request id, the Store's trace, and\n * whether Cloudflare served it from its cache and how old it was. A decision the\n * settings drive for every visitor alike (the maintenance page) can then be\n * traced to the exact request the backend logged, or to a cached copy of it.\n */\nexport interface SettingsAnswer {\n requestId?: string;\n traceId?: string;\n cacheStatus?: string;\n age?: string;\n}\n\nconst ANSWER_HEADERS: Record<keyof SettingsAnswer, string> = {\n requestId: 's-request-id',\n traceId: 'x-trace-id',\n cacheStatus: 'cf-cache-status',\n age: 'age',\n};\n\nfunction settingsAnswerOf(headers: Headers | undefined): SettingsAnswer | undefined {\n if (!headers) return undefined;\n const answer: SettingsAnswer = {};\n for (const [field, name] of Object.entries(ANSWER_HEADERS) as [keyof SettingsAnswer, string][]) {\n const value = headers.get(name);\n if (value) answer[field] = value;\n }\n return Object.keys(answer).length ? answer : undefined;\n}\n\n/**\n * Converts languages object from API to array format.\n * API returns: { \"AR\": { code, name, ... }, \"EN\": { ... } }\n * We need: [{ code, name, ... }, { code, name, ... }]\n * todo:: return the languages as object from the APIs to avoid this\n */\nfunction languagesToArray(languages?: Record<string, Language>): Language[] | undefined {\n if (!languages) return undefined;\n // The SDK's localization modal reads `lang.iso_code` (not `code`) when a language is\n // selected — without it the switch navigates to `/undefined/...`.\n return Object.values(languages).map((lang) => ({ iso_code: lang.code, ...lang }));\n}\n\n/**\n * The settings' analytics context with the native app's headers in it, as Laravel\n * writes it for a Twig theme: the SDK reads the app's platform and version from there.\n * The API answers a server-side call with the engine's own headers, never the app's.\n */\nfunction withNativeAppHeaders(jitsu?: JitsuConfig): JitsuConfig | undefined {\n if (!jitsu || typeof window !== 'undefined') return jitsu;\n let appHeaders: Record<string, string> | null = null;\n try {\n appHeaders = getTwilightContext().nativeAppHeaders;\n } catch {\n return jitsu;\n }\n if (!appHeaders) return jitsu;\n const extra = jitsu.context?.extra;\n // The engine's own app headers go, so an app that sends no version doesn't get the engine's.\n const headers = { ...extra?.headers };\n for (const name of NATIVE_APP_HEADERS) delete headers[name];\n return {\n ...jitsu,\n context: {\n ...jitsu.context,\n extra: { ...extra, headers: { ...headers, ...appHeaders } },\n },\n };\n}\n\nconst SETTINGS_TIMEOUT_MS = 5000;\n\n/**\n * Whether the page's own address switches market (`?scope=`).\n *\n * Only then does the settings request name the scope in its query string. The API\n * reads `?scope=` as a switch and lets it override the market a market's own domain\n * is pinned to, which the `s-scope-id` header never does. Sent on every request, a\n * market remembered from another visit would win over the host the shopper is on: the\n * settings, and the SDK seeded from them, would answer for that market while every\n * call without the parameter (the cart, among them) answers for the host's, and a\n * guest's cart created in one is refused by the other (TD-17588).\n */\nfunction pageSwitchesScope(): boolean {\n return extractScopeFromUrl(`http://page.invalid/${readPageSearch()}`) !== null;\n}\n\nasync function requestSettings(identifier: string): Promise<StoreContext> {\n const includeParams = DEFAULT_INCLUDE_ITEMS.map((i) => `include[]=${i}`).join('&');\n const scope = getActiveScope();\n const params =\n scope != null && pageSwitchesScope() ? `${includeParams}&scope=${scope.id}` : includeParams;\n\n const request = api\n // Sent explicitly rather than left to the client's own resolution, so\n // the identifier this function checked is the identifier that travels.\n // They agree today; a caller passing one and being answered about\n // another is the failure this makes impossible rather than unlikely.\n .get(`store/settings?${params}`, {\n timeout: SETTINGS_TIMEOUT_MS,\n headers: { [STORE_IDENTIFIER_HEADER]: identifier },\n });\n const json = await request.json<{ data?: SettingsApiResponse }>();\n // The same response, already settled; only its headers are read.\n const headers = (await request)?.headers;\n const answer = settingsAnswerOf(headers);\n const devFetchedAt = devSettingsFetchedAt(headers);\n\n const data = json?.data;\n if (!data) {\n throw new SettingsError(\n `The Salla API answered the settings request for store \"${identifier}\" without settings.`,\n { reason: 'empty' }\n );\n }\n\n // Convert languages from object to array\n const languages = languagesToArray(data.languages);\n\n return {\n store: data.store,\n theme: data.theme,\n languages,\n currencies: data.currencies,\n external_services: data.external_services,\n headers: data.headers,\n login: data.login,\n affiliate: data.affiliate,\n policy_url: data.policy_url,\n user: data.user,\n swoole: data.swoole,\n jitsu: withNativeAppHeaders(data.jitsu),\n maintenance: data.maintenance,\n maintenance_details: data.maintenance_details,\n ...(data.maintenance === true &&\n isNotLaunchedNotice(data.maintenance_details) && { launched: false as const }),\n ...(scope && { requestedScopeId: scope.id }),\n ...(answer && { answer }),\n ...(devFetchedAt && { devFetchedAt }),\n };\n}\n\n/** The message the API put in an error body, `{ error: { message } }`, when it sent one. */\nfunction apiErrorMessage(data: unknown): string | undefined {\n const message = (data as { error?: { message?: unknown } } | undefined)?.error?.message;\n return typeof message === 'string' && message.length > 0 && message.length <= 200\n ? message\n : undefined;\n}\n\n/**\n * What core's `CurrentStoreMiddleware` answers, with a 422, when no store has the\n * username or domain it was given (or the store's status is `deleted`). The lookup is\n * `loadUseUsernameOrDomain`, the same one Twig's `checkUsername` turns into its 410.\n * The literal is not translated: it reads the same whatever language was asked for.\n */\nconst STORE_NOT_FOUND_MESSAGE = 'المتجر غير موجود';\n\n/**\n * Whether the API answered that no store has this identifier. A numeric identifier\n * is looked up with `findOrFail`, which Store's exception handler answers with a 410;\n * a username or domain gets {@link STORE_NOT_FOUND_MESSAGE}. A 410 for a username is\n * not read as one: nothing on that path answers it, and a store that does exist must\n * never be told it does not.\n */\nfunction isStoreNotFound(identifier: string, status: number, said: string | undefined): boolean {\n if (status === 410) return parseStoreId(identifier) !== null;\n return status === 422 && said === STORE_NOT_FOUND_MESSAGE;\n}\n\n/**\n * Names what went wrong, because the page, the server log and Sentry all carry\n * this message. Every failure used to read \"Make sure VITE_STORE_DOMAIN is set\",\n * a local-development variable no deployed theme has, so a slow API looked like\n * a misconfigured theme.\n */\nfunction describeSettingsFailure(identifier: string, error: unknown): SettingsError {\n if (error instanceof SettingsError) return error;\n const request = `the settings request for store \"${identifier}\"`;\n if (isTimeoutError(error)) {\n return new SettingsError(\n `The Salla API did not answer ${request} within ${SETTINGS_TIMEOUT_MS} ms.`,\n { reason: 'timeout' }\n );\n }\n if (isHTTPError(error)) {\n const { status } = error.response;\n const said = apiErrorMessage(error.data);\n return new SettingsError(\n `The Salla API answered ${request} with HTTP ${status}${said ? `: ${said}` : ''}.`,\n { reason: isStoreNotFound(identifier, status, said) ? 'not-found' : 'http', status }\n );\n }\n if (isNetworkError(error)) {\n return new SettingsError(`The Salla API could not be reached for ${request}.`, {\n reason: 'network',\n });\n }\n const detail = error instanceof Error ? `: ${error.message}` : '';\n return new SettingsError(`The settings request for store \"${identifier}\" failed${detail}.`);\n}\n\n/**\n * The settings, or a {@link SettingsError} that says why there are none. The\n * query throws it so the root route can say why the store did not load;\n * `store.settings` keeps answering `null` for its own callers.\n */\nasync function fetchSettings(storeIdentifier?: string): Promise<StoreContext> {\n const identifier = storeIdentifier ?? resolveStoreIdentifier();\n\n if (!identifier) {\n const error = new SettingsError(\n 'No store is named for this request: add `?storeId=` on the preview host, or set VITE_STORE_DOMAIN in local development.',\n { reason: 'no-store' }\n );\n console.warn('[store.settings]', error.message);\n throw error;\n }\n\n try {\n return await requestSettings(identifier);\n } catch (cause) {\n const error = describeSettingsFailure(identifier, cause);\n console.error('[store.settings]', error.message, ...(cause === error ? [] : [cause]));\n throw error;\n }\n}\n\nexport const store = {\n settings: async (storeIdentifier?: string): Promise<StoreContext | null> => {\n try {\n return await fetchSettings(storeIdentifier);\n } catch {\n // Already logged, with the reason.\n return null;\n }\n },\n\n queries: {\n settings: (storeIdentifier?: string) =>\n queryOptions<StoreContext | null>({\n queryKey: [\n 'store',\n 'settings',\n storeIdentifier,\n getTwilightContext().locale,\n getActiveScope(),\n // Two versions of one store's settings are two different answers, and\n // this is the query whose answer decides what every other call is\n // pinned to. `requestedThemeVersionId` rather than the resolved one:\n // the resolved value falls back to what these settings report, so it\n // is not knowable until after this query has run — the key would be\n // one thing on the server and another on the client, and the hydrated\n // page would refetch the settings it was just handed.\n requestedThemeVersionId(),\n ],\n // Throws rather than resolving `null`, so the failure keeps its reason.\n queryFn: () => fetchSettings(storeIdentifier),\n // A null never retried, and the root route waits on this: the router's\n // default `retry: 1` would sit through the timeout twice.\n retry: 0,\n }),\n },\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/language-cookie.ts","../src/utils/native-app-headers.ts","../src/api/store.ts"],"names":[],"mappings":"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","file":"chunk-GDLT2GGX.js","sourcesContent":["/**\n * @fileoverview Reading and writing the `s-lang` cookie, on the server and in the browser.\n *\n * The server reads it from the request the framework is handling and writes it to that\n * request's response. The server-only import is stripped from the client bundle by\n * `createIsomorphicFn`, as in `routes/root/beforeLoad.ts`. The browser uses `document.cookie`.\n * Either side outside a request (a prerender, a test) has nothing to read or write and says so\n * quietly.\n */\nimport { createIsomorphicFn } from '@tanstack/react-start';\nimport { getRequestHeader, getRequestUrl, setCookie } from '@tanstack/react-start/server';\nimport { LANGUAGE_COOKIE_MAX_AGE, LANGUAGE_COOKIE_NAME } from './cookies';\n\nconst readServerCookieHeader = createIsomorphicFn()\n .server((): string | null => {\n try {\n return getRequestHeader('cookie') ?? null;\n } catch {\n return null;\n }\n })\n .client((): string | null => null);\n\nconst writeServerLanguageCookie = createIsomorphicFn()\n .server((code: string): void => {\n try {\n setCookie(LANGUAGE_COOKIE_NAME, code, {\n path: '/',\n maxAge: LANGUAGE_COOKIE_MAX_AGE,\n sameSite: 'lax',\n });\n } catch {\n // Outside a request: there is no response to write to.\n }\n })\n .client((): void => {});\n\nconst readServerSearch = createIsomorphicFn()\n .server((): string => {\n try {\n return getRequestUrl().search;\n } catch {\n return '';\n }\n })\n .client((): string => '');\n\n/**\n * The query string of the page being rendered (`?lang=en`, or `''`): the request's on the\n * server, the address bar's in the browser, so both sides read the same one.\n */\nexport function readPageSearch(): string {\n return readServerSearch() || (typeof window !== 'undefined' ? window.location.search : '');\n}\n\n/** The `Cookie` header of the request being handled, or `document.cookie` in the browser. */\nexport function readCookieHeader(): string | null {\n return readServerCookieHeader() ?? (typeof document !== 'undefined' ? document.cookie : null);\n}\n\n/** Remembers `code` as the visitor's language for every store on this host. */\nexport function persistLanguageCookie(code: string): void {\n writeServerLanguageCookie(code);\n if (typeof document !== 'undefined') {\n document.cookie = `${LANGUAGE_COOKIE_NAME}=${encodeURIComponent(code)}; path=/; max-age=${LANGUAGE_COOKIE_MAX_AGE}; SameSite=Lax`;\n }\n}\n","/** The headers the Salla native app sends with every page it loads in its webview. */\nexport const NATIVE_APP_HEADERS = [\n 's-app-os',\n 's-app-version',\n 's-app-full-version',\n 's-app-os-version',\n];\n\n/**\n * The native app's own headers on this request, or null when it is not the app.\n *\n * On a Twig theme Laravel copies them into the settings' `jitsu.context.extra.headers`,\n * where the SDK reads the app's platform and version from (`salla.config.isMobileApp()`).\n * A React theme asks for its settings from the server, through the API, so the app's\n * headers never reach that call: the request is the only place they are.\n */\nexport function readNativeAppHeaders(headers: Headers): Record<string, string> | null {\n const os = headers.get('s-app-os')?.toLowerCase();\n if (os !== 'ios' && os !== 'android') return null;\n const found: Record<string, string> = {};\n for (const name of NATIVE_APP_HEADERS) {\n const value = headers.get(name);\n if (value) found[name] = value;\n }\n return found;\n}\n","import { queryOptions } from '@tanstack/react-query';\nimport { isHTTPError, isNetworkError, isTimeoutError } from 'ky';\nimport { api, getActiveScope, STORE_IDENTIFIER_HEADER } from './client';\nimport { devSettingsFetchedAt } from './dev-settings-cache';\nimport { SettingsError } from '../utils/errors';\nimport type { Store, Theme, Language, JitsuConfig, MaintenanceDetails } from '../types';\nimport { getTwilightContext } from '../twilight/context';\nimport { resolveStoreIdentifier } from '../utils/store-identity';\nimport { extractScopeFromUrl, parseStoreId } from '../utils/cookies';\nimport { readPageSearch } from '../utils/language-cookie';\nimport { requestedThemeVersionId } from '../utils/theme-version';\nimport { NATIVE_APP_HEADERS } from '../utils/native-app-headers';\nimport { isNotLaunchedNotice } from '../utils/maintenance';\n\nexport { resolveStoreIdentifier };\n\nconst DEFAULT_INCLUDE_ITEMS = [\n 'store',\n 'settings',\n 'theme',\n 'theme_settings',\n 'external_services',\n 'currencies',\n 'languages',\n 'payments',\n 'product_widgets',\n 'rating',\n 'ratings',\n 'user',\n];\n\n/** Twig's `salla.init({ user })` object; the endpoint ignores the token, so always the guest. */\nexport interface SettingsUser {\n type: 'guest' | 'user';\n id?: number | string | null;\n language_code?: string;\n currency_code?: string;\n country_code?: string;\n [key: string]: unknown;\n}\n\n/**\n * Raw API response for settings endpoint.\n * Languages come as object: { \"AR\": { code, name, ... }, \"EN\": {...} }\n */\ninterface SettingsApiResponse {\n store?: Store;\n theme?: Theme;\n languages?: Record<string, Language>;\n currencies?: Record<\n string,\n { code: string; name: string; symbol: string; amount: number; country_code: string }\n >;\n external_services?: Record<string, unknown>;\n headers?: Record<string, unknown>;\n login?: { url: string; turnstile_site_key: string };\n affiliate?: { utm_url: string; cta_enabled: boolean };\n debug?: boolean;\n trace_console?: boolean;\n policy_url?: string;\n user?: SettingsUser;\n swoole?: string[];\n jitsu?: JitsuConfig;\n maintenance?: boolean;\n maintenance_details?: MaintenanceDetails;\n}\n\n/**\n * Central settings context - single source of truth for all API data.\n * Contains everything from the settings endpoint response after processing.\n */\nexport interface StoreContext {\n store?: Store;\n theme?: Theme;\n /** Languages as array after conversion from API object format */\n languages?: Language[];\n currencies?: Record<\n string,\n { code: string; name: string; symbol: string; amount: number; country_code: string }\n >;\n external_services?: Record<string, unknown>;\n headers?: Record<string, unknown>;\n login?: { url: string; turnstile_site_key: string };\n affiliate?: { utm_url: string; cta_enabled: boolean };\n debug?: boolean;\n trace_console?: boolean; // todo:: remove it\n policy_url?: string;\n user?: SettingsUser;\n /** API paths the SDK sends with `s-store-api-version: swoole` */\n swoole?: string[];\n /** Where the SDK's analytics send events, and which ones; without it the SDK tracks nothing. */\n jitsu?: JitsuConfig;\n /**\n * The store is closed: by the merchant from the dashboard, by the platform, or\n * for the selected market only. The engine then renders the maintenance page\n * to everyone but the merchant; see `rootBeforeLoad`.\n */\n maintenance?: boolean;\n /** What the maintenance page says; sent beside `maintenance`. */\n maintenance_details?: MaintenanceDetails;\n /**\n * `false` while the store has not launched yet: `maintenance` is then `true` and the\n * engine's maintenance page says the store is launching soon. Absent otherwise. Not\n * from the API: read off `maintenance_details` by `store.settings`, since the\n * backend sends the merchant's \"finish launching\" notice there for every visitor,\n * which is not for a customer's eyes.\n */\n launched?: false;\n /**\n * The scope these settings were requested with; absent when none was. Not from\n * the API: stamped by `store.settings`, so `resolveThemeVersionId` can tell\n * whether the version they name still answers the scope that is active now.\n */\n requestedScopeId?: string;\n /** Which answer of the API these settings are; see {@link SettingsAnswer}. */\n answer?: SettingsAnswer;\n /**\n * When the dev server fetched these settings from the API (epoch ms). It reuses\n * them for a while (see `dev-settings-cache.ts`) and the theme editor says how old\n * they are. Only on a dev server render; absent everywhere else.\n */\n devFetchedAt?: number;\n}\n\n/**\n * Which answer of the settings API a set of settings came from, read off the\n * response rather than the body: the API's request id, the Store's trace, and\n * whether Cloudflare served it from its cache and how old it was. A decision the\n * settings drive for every visitor alike (the maintenance page) can then be\n * traced to the exact request the backend logged, or to a cached copy of it.\n */\nexport interface SettingsAnswer {\n requestId?: string;\n traceId?: string;\n cacheStatus?: string;\n age?: string;\n}\n\nconst ANSWER_HEADERS: Record<keyof SettingsAnswer, string> = {\n requestId: 's-request-id',\n traceId: 'x-trace-id',\n cacheStatus: 'cf-cache-status',\n age: 'age',\n};\n\nfunction settingsAnswerOf(headers: Headers | undefined): SettingsAnswer | undefined {\n if (!headers) return undefined;\n const answer: SettingsAnswer = {};\n for (const [field, name] of Object.entries(ANSWER_HEADERS) as [keyof SettingsAnswer, string][]) {\n const value = headers.get(name);\n if (value) answer[field] = value;\n }\n return Object.keys(answer).length ? answer : undefined;\n}\n\n/**\n * Converts languages object from API to array format.\n * API returns: { \"AR\": { code, name, ... }, \"EN\": { ... } }\n * We need: [{ code, name, ... }, { code, name, ... }]\n * todo:: return the languages as object from the APIs to avoid this\n */\nfunction languagesToArray(languages?: Record<string, Language>): Language[] | undefined {\n if (!languages) return undefined;\n // The SDK's localization modal reads `lang.iso_code` (not `code`) when a language is\n // selected — without it the switch navigates to `/undefined/...`.\n return Object.values(languages).map((lang) => ({ iso_code: lang.code, ...lang }));\n}\n\n/**\n * The settings' analytics context with the native app's headers in it, as Laravel\n * writes it for a Twig theme: the SDK reads the app's platform and version from there.\n * The API answers a server-side call with the engine's own headers, never the app's.\n */\nfunction withNativeAppHeaders(jitsu?: JitsuConfig): JitsuConfig | undefined {\n if (!jitsu || typeof window !== 'undefined') return jitsu;\n let appHeaders: Record<string, string> | null = null;\n try {\n appHeaders = getTwilightContext().nativeAppHeaders;\n } catch {\n return jitsu;\n }\n if (!appHeaders) return jitsu;\n const extra = jitsu.context?.extra;\n // The engine's own app headers go, so an app that sends no version doesn't get the engine's.\n const headers = { ...extra?.headers };\n for (const name of NATIVE_APP_HEADERS) delete headers[name];\n return {\n ...jitsu,\n context: {\n ...jitsu.context,\n extra: { ...extra, headers: { ...headers, ...appHeaders } },\n },\n };\n}\n\nconst SETTINGS_TIMEOUT_MS = 5000;\n\n/**\n * Whether the page's own address switches market (`?scope=`).\n *\n * Only then does the settings request name the scope in its query string. The API\n * reads `?scope=` as a switch and lets it override the market a market's own domain\n * is pinned to, which the `s-scope-id` header never does. Sent on every request, a\n * market remembered from another visit would win over the host the shopper is on: the\n * settings, and the SDK seeded from them, would answer for that market while every\n * call without the parameter (the cart, among them) answers for the host's, and a\n * guest's cart created in one is refused by the other (TD-17588).\n */\nfunction pageSwitchesScope(): boolean {\n return extractScopeFromUrl(`http://page.invalid/${readPageSearch()}`) !== null;\n}\n\nasync function requestSettings(identifier: string): Promise<StoreContext> {\n const includeParams = DEFAULT_INCLUDE_ITEMS.map((i) => `include[]=${i}`).join('&');\n const scope = getActiveScope();\n const params =\n scope != null && pageSwitchesScope() ? `${includeParams}&scope=${scope.id}` : includeParams;\n\n const request = api\n // Sent explicitly rather than left to the client's own resolution, so\n // the identifier this function checked is the identifier that travels.\n // They agree today; a caller passing one and being answered about\n // another is the failure this makes impossible rather than unlikely.\n .get(`store/settings?${params}`, {\n timeout: SETTINGS_TIMEOUT_MS,\n headers: { [STORE_IDENTIFIER_HEADER]: identifier },\n });\n const json = await request.json<{ data?: SettingsApiResponse }>();\n // The same response, already settled; only its headers are read.\n const headers = (await request)?.headers;\n const answer = settingsAnswerOf(headers);\n const devFetchedAt = devSettingsFetchedAt(headers);\n\n const data = json?.data;\n if (!data) {\n throw new SettingsError(\n `The Salla API answered the settings request for store \"${identifier}\" without settings.`,\n { reason: 'empty' }\n );\n }\n\n // Convert languages from object to array\n const languages = languagesToArray(data.languages);\n\n return {\n store: data.store,\n theme: data.theme,\n languages,\n currencies: data.currencies,\n external_services: data.external_services,\n headers: data.headers,\n login: data.login,\n affiliate: data.affiliate,\n policy_url: data.policy_url,\n user: data.user,\n swoole: data.swoole,\n jitsu: withNativeAppHeaders(data.jitsu),\n maintenance: data.maintenance,\n maintenance_details: data.maintenance_details,\n ...(data.maintenance === true &&\n isNotLaunchedNotice(data.maintenance_details) && { launched: false as const }),\n ...(scope && { requestedScopeId: scope.id }),\n ...(answer && { answer }),\n ...(devFetchedAt && { devFetchedAt }),\n };\n}\n\n/** The message the API put in an error body, `{ error: { message } }`, when it sent one. */\nfunction apiErrorMessage(data: unknown): string | undefined {\n const message = (data as { error?: { message?: unknown } } | undefined)?.error?.message;\n return typeof message === 'string' && message.length > 0 && message.length <= 200\n ? message\n : undefined;\n}\n\n/**\n * What core's `CurrentStoreMiddleware` answers, with a 422, when no store has the\n * username or domain it was given (or the store's status is `deleted`). The lookup is\n * `loadUseUsernameOrDomain`, the same one Twig's `checkUsername` turns into its 410.\n * The literal is not translated: it reads the same whatever language was asked for.\n */\nconst STORE_NOT_FOUND_MESSAGE = 'المتجر غير موجود';\n\n/**\n * Whether the API answered that no store has this identifier. A numeric identifier\n * is looked up with `findOrFail`, which Store's exception handler answers with a 410;\n * a username or domain gets {@link STORE_NOT_FOUND_MESSAGE}. A 410 for a username is\n * not read as one: nothing on that path answers it, and a store that does exist must\n * never be told it does not.\n */\nfunction isStoreNotFound(identifier: string, status: number, said: string | undefined): boolean {\n if (status === 410) return parseStoreId(identifier) !== null;\n return status === 422 && said === STORE_NOT_FOUND_MESSAGE;\n}\n\n/**\n * Names what went wrong, because the page, the server log and Sentry all carry\n * this message. Every failure used to read \"Make sure VITE_STORE_DOMAIN is set\",\n * a local-development variable no deployed theme has, so a slow API looked like\n * a misconfigured theme.\n */\nfunction describeSettingsFailure(identifier: string, error: unknown): SettingsError {\n if (error instanceof SettingsError) return error;\n const request = `the settings request for store \"${identifier}\"`;\n if (isTimeoutError(error)) {\n return new SettingsError(\n `The Salla API did not answer ${request} within ${SETTINGS_TIMEOUT_MS} ms.`,\n { reason: 'timeout' }\n );\n }\n if (isHTTPError(error)) {\n const { status } = error.response;\n const said = apiErrorMessage(error.data);\n return new SettingsError(\n `The Salla API answered ${request} with HTTP ${status}${said ? `: ${said}` : ''}.`,\n { reason: isStoreNotFound(identifier, status, said) ? 'not-found' : 'http', status }\n );\n }\n if (isNetworkError(error)) {\n return new SettingsError(`The Salla API could not be reached for ${request}.`, {\n reason: 'network',\n });\n }\n const detail = error instanceof Error ? `: ${error.message}` : '';\n return new SettingsError(`The settings request for store \"${identifier}\" failed${detail}.`);\n}\n\n/**\n * The settings, or a {@link SettingsError} that says why there are none. The\n * query throws it so the root route can say why the store did not load;\n * `store.settings` keeps answering `null` for its own callers.\n */\nasync function fetchSettings(storeIdentifier?: string): Promise<StoreContext> {\n const identifier = storeIdentifier ?? resolveStoreIdentifier();\n\n if (!identifier) {\n const error = new SettingsError(\n 'No store is named for this request: add `?storeId=` on the preview host, or set VITE_STORE_DOMAIN in local development.',\n { reason: 'no-store' }\n );\n console.warn('[store.settings]', error.message);\n throw error;\n }\n\n try {\n return await requestSettings(identifier);\n } catch (cause) {\n const error = describeSettingsFailure(identifier, cause);\n console.error('[store.settings]', error.message, ...(cause === error ? [] : [cause]));\n throw error;\n }\n}\n\nexport const store = {\n settings: async (storeIdentifier?: string): Promise<StoreContext | null> => {\n try {\n return await fetchSettings(storeIdentifier);\n } catch {\n // Already logged, with the reason.\n return null;\n }\n },\n\n queries: {\n settings: (storeIdentifier?: string) =>\n queryOptions<StoreContext | null>({\n queryKey: [\n 'store',\n 'settings',\n storeIdentifier,\n getTwilightContext().locale,\n getActiveScope(),\n // Two versions of one store's settings are two different answers, and\n // this is the query whose answer decides what every other call is\n // pinned to. `requestedThemeVersionId` rather than the resolved one:\n // the resolved value falls back to what these settings report, so it\n // is not knowable until after this query has run — the key would be\n // one thing on the server and another on the client, and the hydrated\n // page would refetch the settings it was just handed.\n requestedThemeVersionId(),\n ],\n // Throws rather than resolving `null`, so the failure keeps its reason.\n queryFn: () => fetchSettings(storeIdentifier),\n // A null never retried, and the root route waits on this: the router's\n // default `retry: 1` would sit through the timeout twice.\n retry: 0,\n }),\n },\n};\n"]}
|
|
@@ -147,7 +147,7 @@ function takeFrameReport(message) {
|
|
|
147
147
|
async function answerLookup(message) {
|
|
148
148
|
const { requestId, source, query } = message;
|
|
149
149
|
try {
|
|
150
|
-
const { lookupInStore } = await import('./store-lookup-
|
|
150
|
+
const { lookupInStore } = await import('./store-lookup-MDUKB5VN.js');
|
|
151
151
|
sendToEditor({ kind: "lookup-result", requestId, items: await lookupInStore(source, query) });
|
|
152
152
|
} catch (error) {
|
|
153
153
|
sendToEditor({
|
|
@@ -500,5 +500,5 @@ function useDevLayoutBlocks(components) {
|
|
|
500
500
|
var useDevHomeBlocks = import.meta.env.DEV ? useDevLayoutBlocks : (components) => components;
|
|
501
501
|
|
|
502
502
|
export { blockPath, devSettingsStore, useDevEditorMeta, useDevHomeBlocks, useDevReportSettingsFetchedAt, useDevSettingsOverrides, useDevSettingsState };
|
|
503
|
-
//# sourceMappingURL=chunk-
|
|
504
|
-
//# sourceMappingURL=chunk-
|
|
503
|
+
//# sourceMappingURL=chunk-JKSDTWEC.js.map
|
|
504
|
+
//# sourceMappingURL=chunk-JKSDTWEC.js.map
|