@salla.sa/twilight-theme-engine 1.0.138 → 1.0.140
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-P3IXCYO7.js → AddToCartForm-EPTN5O3X.js} +3 -3
- package/dist/{AddToCartForm-P3IXCYO7.js.map → AddToCartForm-EPTN5O3X.js.map} +1 -1
- package/dist/{BlogAuthorPage-UJYMW4ZL.js → BlogAuthorPage-PGFINJSP.js} +16 -16
- package/dist/{BlogAuthorPage-UJYMW4ZL.js.map → BlogAuthorPage-PGFINJSP.js.map} +1 -1
- package/dist/{BlogCategoryPage-3XO42UFX.js → BlogCategoryPage-ZVRRHTKJ.js} +16 -16
- package/dist/{BlogCategoryPage-3XO42UFX.js.map → BlogCategoryPage-ZVRRHTKJ.js.map} +1 -1
- package/dist/{BlogPage-5SQNDQ7L.js → BlogPage-5SRGR7NK.js} +14 -14
- package/dist/{BlogPage-5SQNDQ7L.js.map → BlogPage-5SRGR7NK.js.map} +1 -1
- package/dist/{BlogSinglePage-XSRKZYUI.js → BlogSinglePage-6A5J2BKK.js} +14 -14
- package/dist/{BlogSinglePage-XSRKZYUI.js.map → BlogSinglePage-6A5J2BKK.js.map} +1 -1
- package/dist/{BlogTagPage-CFXWHUJR.js → BlogTagPage-DAA3ZO76.js} +16 -16
- package/dist/{BlogTagPage-CFXWHUJR.js.map → BlogTagPage-DAA3ZO76.js.map} +1 -1
- package/dist/{BrandsPage-APYVP4M2.js → BrandsPage-JABKRWP2.js} +15 -15
- package/dist/{BrandsPage-APYVP4M2.js.map → BrandsPage-JABKRWP2.js.map} +1 -1
- package/dist/{Breadcrumb-M4DBOMXW.js → Breadcrumb-SCJZW4RO.js} +14 -14
- package/dist/{Breadcrumb-M4DBOMXW.js.map → Breadcrumb-SCJZW4RO.js.map} +1 -1
- package/dist/{CartItem-BXZDBDLA.js → CartItem-3KFTPQVF.js} +14 -14
- package/dist/{CartItem-BXZDBDLA.js.map → CartItem-3KFTPQVF.js.map} +1 -1
- package/dist/{CartSummary-NT7N6ERQ.js → CartSummary-I64SD4QX.js} +14 -14
- package/dist/{CartSummary-NT7N6ERQ.js.map → CartSummary-I64SD4QX.js.map} +1 -1
- package/dist/{Copyright-IJDVQWOS.js → Copyright-3TREUCAK.js} +3 -3
- package/dist/{Copyright-IJDVQWOS.js.map → Copyright-3TREUCAK.js.map} +1 -1
- package/dist/{CustomerLayout-UNEDHUO2.js → CustomerLayout-BH74QWRI.js} +14 -14
- package/dist/{CustomerLayout-UNEDHUO2.js.map → CustomerLayout-BH74QWRI.js.map} +1 -1
- package/dist/{Footer-QX5BCDUK.js → Footer-DSSOB3ZW.js} +4 -4
- package/dist/{Footer-QX5BCDUK.js.map → Footer-DSSOB3ZW.js.map} +1 -1
- package/dist/{Header-EAOIXJNS.js → Header-UWUS34D6.js} +8 -8
- package/dist/{Header-EAOIXJNS.js.map → Header-UWUS34D6.js.map} +1 -1
- package/dist/LatestProducts-VLSTOKEB.js +107 -0
- package/dist/LatestProducts-VLSTOKEB.js.map +1 -0
- package/dist/{LoyaltyPage-3VOLW5OQ.js → LoyaltyPage-3FAD5MJ6.js} +14 -14
- package/dist/{LoyaltyPage-3VOLW5OQ.js.map → LoyaltyPage-3FAD5MJ6.js.map} +1 -1
- package/dist/{LoyaltyPointsPage-IMHJHCZV.js → LoyaltyPointsPage-A4CTI55P.js} +6 -6
- package/dist/{LoyaltyPointsPage-IMHJHCZV.js.map → LoyaltyPointsPage-A4CTI55P.js.map} +1 -1
- package/dist/{MainMenu-ML6OQT53.js → MainMenu-C7TWXVL5.js} +6 -6
- package/dist/MainMenu-C7TWXVL5.js.map +1 -0
- package/dist/{MasterLayout-UCQA73I3.js → MasterLayout-MZY44RTA.js} +14 -14
- package/dist/{MasterLayout-UCQA73I3.js.map → MasterLayout-MZY44RTA.js.map} +1 -1
- package/dist/{MobileMenu-5JHOT4DP.js → MobileMenu-KNDN34HO.js} +15 -15
- package/dist/{MobileMenu-5JHOT4DP.js.map → MobileMenu-KNDN34HO.js.map} +1 -1
- package/dist/NoContent-7A7OR2NZ.js +6 -0
- package/dist/NoContent-7A7OR2NZ.js.map +1 -0
- package/dist/{NotificationsPage-C373Z2KC.js → NotificationsPage-LKUTYWPR.js} +14 -14
- package/dist/{NotificationsPage-C373Z2KC.js.map → NotificationsPage-LKUTYWPR.js.map} +1 -1
- package/dist/{OrderSinglePage-YYTU72JY.js → OrderSinglePage-VDALCKJL.js} +15 -15
- package/dist/{OrderSinglePage-YYTU72JY.js.map → OrderSinglePage-VDALCKJL.js.map} +1 -1
- package/dist/{OrdersPage-2F43AA76.js → OrdersPage-TOSCY6ML.js} +14 -14
- package/dist/{OrdersPage-2F43AA76.js.map → OrdersPage-TOSCY6ML.js.map} +1 -1
- package/dist/{PageSingle-2FIESLYJ.js → PageSingle-56SRDA4Q.js} +3 -3
- package/dist/{PageSingle-2FIESLYJ.js.map → PageSingle-56SRDA4Q.js.map} +1 -1
- package/dist/{ProductDetails-TNULRGXM.js → ProductDetails-YYU7TJSU.js} +4 -4
- package/dist/{ProductDetails-TNULRGXM.js.map → ProductDetails-YYU7TJSU.js.map} +1 -1
- package/dist/{ProfilePage-4VSU6H3S.js → ProfilePage-CTGBAD2A.js} +14 -14
- package/dist/{ProfilePage-4VSU6H3S.js.map → ProfilePage-CTGBAD2A.js.map} +1 -1
- package/dist/{ReviewsPage-65CYIATI.js → ReviewsPage-RJ5VQVB2.js} +3 -3
- package/dist/{ReviewsPage-65CYIATI.js.map → ReviewsPage-RJ5VQVB2.js.map} +1 -1
- package/dist/{SeoCartWidget-UHJJLLCU.js → SeoCartWidget-VL5TD2FU.js} +14 -14
- package/dist/{SeoCartWidget-UHJJLLCU.js.map → SeoCartWidget-VL5TD2FU.js.map} +1 -1
- package/dist/{SettingsPage-2JHRIGFS.js → SettingsPage-ZHDB3YZS.js} +14 -14
- package/dist/{SettingsPage-2JHRIGFS.js.map → SettingsPage-ZHDB3YZS.js.map} +1 -1
- package/dist/{StoreClosedNotification-ADSYNO7O.js → StoreClosedNotification-VP2ACWD6.js} +15 -15
- package/dist/{StoreClosedNotification-ADSYNO7O.js.map → StoreClosedNotification-VP2ACWD6.js.map} +1 -1
- package/dist/{TestimonialsPage-PYFKXCQP.js → TestimonialsPage-V2RWUVZD.js} +3 -3
- package/dist/{TestimonialsPage-PYFKXCQP.js.map → TestimonialsPage-V2RWUVZD.js.map} +1 -1
- package/dist/{ThankYouPage-VHUAKQF7.js → ThankYouPage-NJKASZ2R.js} +14 -14
- package/dist/{ThankYouPage-VHUAKQF7.js.map → ThankYouPage-NJKASZ2R.js.map} +1 -1
- package/dist/{WalletPage-NG2DJAUE.js → WalletPage-N4FDKDK3.js} +15 -15
- package/dist/{WalletPage-NG2DJAUE.js.map → WalletPage-N4FDKDK3.js.map} +1 -1
- package/dist/{WishlistPage-GFOKEWL3.js → WishlistPage-JCOG3KOV.js} +16 -16
- package/dist/{WishlistPage-GFOKEWL3.js.map → WishlistPage-JCOG3KOV.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-MWAXFBGG.js → chunk-2AS6KREO.js} +3 -3
- package/dist/{chunk-MWAXFBGG.js.map → chunk-2AS6KREO.js.map} +1 -1
- package/dist/{NoContent-63TMCPGY.js → chunk-33FWLJXY.js} +2 -4
- package/dist/chunk-33FWLJXY.js.map +1 -0
- package/dist/{chunk-35D6CKKX.js → chunk-33R2PXOK.js} +4 -4
- package/dist/{chunk-35D6CKKX.js.map → chunk-33R2PXOK.js.map} +1 -1
- package/dist/{chunk-OSYUGCRG.js → chunk-3CKMMFUF.js} +4 -4
- package/dist/{chunk-OSYUGCRG.js.map → chunk-3CKMMFUF.js.map} +1 -1
- package/dist/{chunk-SAYYMA6E.js → chunk-444GCMTZ.js} +21 -9
- package/dist/chunk-444GCMTZ.js.map +1 -0
- package/dist/{chunk-PBFLXHKM.js → chunk-5NTD7WXX.js} +3 -3
- package/dist/{chunk-PBFLXHKM.js.map → chunk-5NTD7WXX.js.map} +1 -1
- package/dist/{chunk-FVHAKOEH.js → chunk-7DRXAR76.js} +3 -3
- package/dist/{chunk-FVHAKOEH.js.map → chunk-7DRXAR76.js.map} +1 -1
- package/dist/{chunk-U6EB7GM3.js → chunk-7PFJOTZS.js} +4 -4
- package/dist/{chunk-U6EB7GM3.js.map → chunk-7PFJOTZS.js.map} +1 -1
- package/dist/{chunk-P43VADN7.js → chunk-ABVHWJPY.js} +10 -3
- package/dist/chunk-ABVHWJPY.js.map +1 -0
- package/dist/{chunk-S7FNMT24.js → chunk-AEM5UEH6.js} +3 -3
- package/dist/{chunk-S7FNMT24.js.map → chunk-AEM5UEH6.js.map} +1 -1
- package/dist/{chunk-HG75MP47.js → chunk-ATL7CYF2.js} +3 -3
- package/dist/{chunk-HG75MP47.js.map → chunk-ATL7CYF2.js.map} +1 -1
- package/dist/{chunk-KLVEKLFL.js → chunk-AZT4TALZ.js} +5 -5
- package/dist/{chunk-KLVEKLFL.js.map → chunk-AZT4TALZ.js.map} +1 -1
- package/dist/{chunk-S5ZKI3TY.js → chunk-BPM6LSOV.js} +4 -4
- package/dist/{chunk-S5ZKI3TY.js.map → chunk-BPM6LSOV.js.map} +1 -1
- package/dist/{chunk-JXLZTGQN.js → chunk-CU2DV3Z4.js} +3 -3
- package/dist/{chunk-JXLZTGQN.js.map → chunk-CU2DV3Z4.js.map} +1 -1
- package/dist/chunk-F3SXHQU4.js +206 -0
- package/dist/chunk-F3SXHQU4.js.map +1 -0
- package/dist/{chunk-WC2ZDV4J.js → chunk-GIYRCRS6.js} +3 -3
- package/dist/{chunk-WC2ZDV4J.js.map → chunk-GIYRCRS6.js.map} +1 -1
- package/dist/{chunk-5FEFYFTS.js → chunk-IK7CQSEA.js} +3 -3
- package/dist/{chunk-5FEFYFTS.js.map → chunk-IK7CQSEA.js.map} +1 -1
- package/dist/{chunk-UXS3QCHM.js → chunk-J4EFCWMM.js} +14 -14
- package/dist/{chunk-UXS3QCHM.js.map → chunk-J4EFCWMM.js.map} +1 -1
- package/dist/{chunk-TK6A4UON.js → chunk-LB4U7GI3.js} +4 -4
- package/dist/{chunk-TK6A4UON.js.map → chunk-LB4U7GI3.js.map} +1 -1
- package/dist/{chunk-LMMDVLAB.js → chunk-LCRHHSBP.js} +7 -5
- package/dist/chunk-LCRHHSBP.js.map +1 -0
- package/dist/{chunk-EGJ2SV6O.js → chunk-LGXEXLX3.js} +12 -12
- package/dist/chunk-LGXEXLX3.js.map +1 -0
- package/dist/{chunk-GJFK3SU5.js → chunk-MBU4LSRZ.js} +4 -4
- package/dist/{chunk-GJFK3SU5.js.map → chunk-MBU4LSRZ.js.map} +1 -1
- package/dist/{chunk-EJ66I5SH.js → chunk-MJ3DLAC3.js} +4 -4
- package/dist/{chunk-EJ66I5SH.js.map → chunk-MJ3DLAC3.js.map} +1 -1
- package/dist/{chunk-DMS6PZXN.js → chunk-MOAMYULW.js} +4 -4
- package/dist/{chunk-DMS6PZXN.js.map → chunk-MOAMYULW.js.map} +1 -1
- package/dist/{chunk-3QR6T7KW.js → chunk-N36TVQP2.js} +6 -201
- package/dist/chunk-N36TVQP2.js.map +1 -0
- package/dist/{chunk-VFQNVPFH.js → chunk-NRPYHHRQ.js} +7 -7
- package/dist/{chunk-VFQNVPFH.js.map → chunk-NRPYHHRQ.js.map} +1 -1
- package/dist/{chunk-6KZUGNCS.js → chunk-NUTURBAK.js} +3 -3
- package/dist/{chunk-6KZUGNCS.js.map → chunk-NUTURBAK.js.map} +1 -1
- package/dist/{chunk-EOQPV6KS.js → chunk-O2RXB3P3.js} +7 -7
- package/dist/{chunk-EOQPV6KS.js.map → chunk-O2RXB3P3.js.map} +1 -1
- package/dist/{chunk-HEWFF3KI.js → chunk-OEM2SFJE.js} +3 -3
- package/dist/{chunk-HEWFF3KI.js.map → chunk-OEM2SFJE.js.map} +1 -1
- package/dist/{chunk-A7KXUBPT.js → chunk-OJMG3NAF.js} +3 -3
- package/dist/{chunk-A7KXUBPT.js.map → chunk-OJMG3NAF.js.map} +1 -1
- package/dist/{chunk-TVAXTMMQ.js → chunk-QQWJNRSI.js} +3 -3
- package/dist/{chunk-TVAXTMMQ.js.map → chunk-QQWJNRSI.js.map} +1 -1
- package/dist/{chunk-6EOAIIHL.js → chunk-RUUQ5OVU.js} +3 -3
- package/dist/{chunk-6EOAIIHL.js.map → chunk-RUUQ5OVU.js.map} +1 -1
- package/dist/{chunk-R73HXW5D.js → chunk-SCBSKIBA.js} +4 -4
- package/dist/{chunk-R73HXW5D.js.map → chunk-SCBSKIBA.js.map} +1 -1
- package/dist/{chunk-ITZ543CK.js → chunk-SOLUKKTW.js} +3 -3
- package/dist/{chunk-ITZ543CK.js.map → chunk-SOLUKKTW.js.map} +1 -1
- package/dist/{chunk-TWLJ2RII.js → chunk-TDIENKPW.js} +4 -4
- package/dist/{chunk-TWLJ2RII.js.map → chunk-TDIENKPW.js.map} +1 -1
- package/dist/{chunk-5MNGLNIJ.js → chunk-UXJAZ5JP.js} +3 -3
- package/dist/{chunk-5MNGLNIJ.js.map → chunk-UXJAZ5JP.js.map} +1 -1
- package/dist/{chunk-JFKHKDSK.js → chunk-VNZ6VI2O.js} +3 -3
- package/dist/{chunk-JFKHKDSK.js.map → chunk-VNZ6VI2O.js.map} +1 -1
- package/dist/{chunk-OXBMZSKL.js → chunk-VXMWMGBQ.js} +4 -4
- package/dist/{chunk-OXBMZSKL.js.map → chunk-VXMWMGBQ.js.map} +1 -1
- package/dist/{chunk-YPRSS27D.js → chunk-XMSZSSTZ.js} +4 -4
- package/dist/{chunk-YPRSS27D.js.map → chunk-XMSZSSTZ.js.map} +1 -1
- package/dist/{chunk-R4BPODDJ.js → chunk-YRIMECFU.js} +3 -3
- package/dist/{chunk-R4BPODDJ.js.map → chunk-YRIMECFU.js.map} +1 -1
- package/dist/{chunk-CJZ3MJ3Y.js → chunk-ZNA3SWRP.js} +7 -7
- package/dist/{chunk-CJZ3MJ3Y.js.map → chunk-ZNA3SWRP.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 +3 -1
- package/dist/components/home/HomePageRenderer.d.ts.map +1 -1
- package/dist/components/home/LatestProducts.d.ts +13 -0
- package/dist/components/home/LatestProducts.d.ts.map +1 -0
- package/dist/components/home/index.js +17 -16
- package/dist/components/home/lazy.d.ts +1 -0
- package/dist/components/home/lazy.d.ts.map +1 -1
- package/dist/components/home/register.d.ts.map +1 -1
- package/dist/components/layout/index.js +4 -4
- package/dist/components/navigation/MainMenu.d.ts.map +1 -1
- package/dist/components/product/index.js +14 -13
- 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-IGGYSGCU.js → document-class-B4WBGWSA.js} +11 -11
- package/dist/{document-class-IGGYSGCU.js.map → document-class-B4WBGWSA.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-MJYWGH7A.js → navigation-MBQKDV5V.js} +5 -5
- package/dist/{navigation-MJYWGH7A.js.map → navigation-MBQKDV5V.js.map} +1 -1
- package/dist/{navigation-FUHRDRAN.js → navigation-VPRCR725.js} +4 -4
- package/dist/{navigation-FUHRDRAN.js.map → navigation-VPRCR725.js.map} +1 -1
- package/dist/{not-found-VVI6BXAZ.js → not-found-OIZGDR7G.js} +15 -15
- package/dist/{not-found-VVI6BXAZ.js.map → not-found-OIZGDR7G.js.map} +1 -1
- package/dist/providers/index.js +12 -12
- package/dist/routes/account/orders.js +4 -4
- 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 -20
- package/dist/routes/cart.js.map +1 -1
- package/dist/routes/home/HomePage.d.ts.map +1 -1
- package/dist/routes/home.js +18 -17
- 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 -18
- package/dist/routes/product-listing.js.map +1 -1
- package/dist/routes/product.js +17 -16
- package/dist/routes/product.js.map +1 -1
- package/dist/routes/root/beforeLoad.d.ts.map +1 -1
- 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 -17
- package/dist/{store-lookup-2P7PQVXE.js → store-lookup-HMU7QMSC.js} +8 -8
- package/dist/{store-lookup-2P7PQVXE.js.map → store-lookup-HMU7QMSC.js.map} +1 -1
- package/dist/tanstack/link.d.ts.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 +14 -3
- package/tailwind/components/home/LatestProducts.tsx.txt +63 -0
- package/tailwind/components/home/lazy.ts.txt +4 -0
- package/tailwind/components/home/register.ts.txt +2 -0
- package/tailwind/components/navigation/MainMenu.tsx.txt +2 -1
- package/tailwind/routes/home/HomePage.tsx.txt +6 -0
- package/tailwind/routes/root/beforeLoad.ts.txt +4 -2
- package/dist/MainMenu-ML6OQT53.js.map +0 -1
- package/dist/NoContent-63TMCPGY.js.map +0 -1
- package/dist/chunk-3QR6T7KW.js.map +0 -1
- package/dist/chunk-EGJ2SV6O.js.map +0 -1
- package/dist/chunk-LMMDVLAB.js.map +0 -1
- package/dist/chunk-P43VADN7.js.map +0 -1
- package/dist/chunk-SAYYMA6E.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/dev/dev-settings-store.ts"],"names":["block"],"mappings":"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","file":"chunk-S7FNMT24.js","sourcesContent":["/**\n * Client-side store for the dev editor: theme-setting overrides and a dev-owned\n * home layout. Saved to `twilight.preview.json` through the dev server (see\n * `twilight-schema.plugin.ts`), not to localStorage, for three reasons: the\n * server render can read a file, so the page hydrates with the edited layout\n * instead of flashing the store's; the state survives a port or browser\n * change; and the developer can open, diff or delete it.\n *\n * The saved state reaches this module through `virtual:twilight/schema`, which\n * the root route imports on both sides before anything renders and which puts\n * it on `globalThis[DEV_PREVIEW_GLOBAL]`. Server snapshots read that value\n * (the server's modules are re-run after each save); the browser copies it once\n * and then owns the state.\n *\n * The theme editor (`/__twilight/editor`) frames the storefront, so two copies\n * of this store run side by side. Edits reach every copy on the origin at once\n * over a `BroadcastChannel` (the file save is debounced), and only the copy\n * that made an edit saves it. Everything else between an editor and its frame\n * (the home page's blocks, the store base, scroll-to-block) goes by\n * `postMessage` to that one window, so another storefront tab never answers.\n */\n\nimport { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';\nimport {\n DEV_LOOKUP_TIMEOUT_MS,\n DEV_PREVIEW_ENDPOINT,\n DEV_PREVIEW_EVENT,\n DEV_PREVIEW_GLOBAL,\n EMPTY_PREVIEW_STATE,\n isEditorFrame,\n normalizePreviewState,\n type DevLookupItem,\n type DevLookupSource,\n type DevPreviewBlock,\n type DevPreviewState,\n type DevSchema,\n} from './schema-types';\nimport { resolveStoreBase } from '../utils/store-identity';\n\nexport type DevSettingsState = DevPreviewState;\nexport type DevSaveStatus = 'idle' | 'saving' | 'saved' | 'error';\ntype LiveBlocks = { path?: string }[];\n\n/** Where the old localStorage-backed widget kept its state; migrated once. */\nconst LEGACY_STORAGE_KEY = 'twilight:dev-settings';\n/** Batch keystrokes into one write. */\nconst SAVE_DELAY_MS = 250;\n/** Same-browser channel every copy of the store listens on, for edits. */\nconst CHANNEL_NAME = 'twilight:preview';\n/** Envelope type of the editor ↔ frame `postMessage`s. */\nconst FRAME_MESSAGE = 'twilight:editor';\n/** How long the frame keeps looking for a block that is still rendering (just added, say). */\nconst FOCUS_WAIT_MS = 2000;\nconst FOCUS_FLASH_MS = 1200;\n\n/** Editor ↔ the storefront it frames. */\ntype FrameMessage =\n | { kind: 'live-blocks'; blocks: LiveBlocks | null }\n | { kind: 'frame-info'; base: string | null }\n | { kind: 'settings-fetched'; at: number }\n | { kind: 'request-live-blocks' }\n | { kind: 'focus-block'; index: number }\n | { kind: 'lookup'; requestId: string; source: DevLookupSource; query: string }\n | { kind: 'lookup-result'; requestId: string; items?: DevLookupItem[]; error?: string };\n\ninterface PendingLookup {\n resolve: (items: DevLookupItem[]) => void;\n reject: (error: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n}\nconst pendingLookups = new Map<string, PendingLookup>();\n\n/** What the editor shows besides the saved state. */\nexport interface DevEditorMeta {\n /** The blocks the framed home page shows; `null` when it is not on the home page. */\n liveBlocks: LiveBlocks | null;\n saveStatus: DevSaveStatus;\n /** The frame's store segment; `undefined` until the frame has said. */\n frameBase: string | null | undefined;\n /**\n * When the dev server last asked the API for the frame's store settings (epoch\n * ms), which it reuses for a while (see `api/dev-settings-cache.ts`); `null`\n * until the frame says.\n */\n settingsFetchedAt: number | null;\n}\n\n/**\n * A short random hex id. `getRandomValues`, not `randomUUID`: the latter only\n * exists in secure contexts, and the dev server may be opened on a LAN address.\n */\nfunction randomId(bytes = 6): string {\n const values = globalThis.crypto.getRandomValues(new Uint8Array(bytes));\n return Array.from(values, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nlet tabId: string | undefined;\n\n/**\n * Sent with every save so this tab can ignore its own broadcast. Made on first\n * use, never at module load: Cloudflare Workers refuse random values in global\n * scope, and this module is in the worker bundle (its use is dev-only, its\n * top level is not).\n */\nfunction myTabId(): string {\n tabId ??= randomId();\n return tabId;\n}\n\nlet seedSource: unknown;\nlet seedState: DevPreviewState = EMPTY_PREVIEW_STATE;\n\n/** The saved file as this page loaded it, normalized once per value so snapshots keep their identity. */\nfunction readSeed(): DevPreviewState {\n const raw = (globalThis as Record<string, unknown>)[DEV_PREVIEW_GLOBAL];\n if (raw !== seedSource) {\n seedSource = raw;\n seedState = normalizePreviewState(raw) ?? EMPTY_PREVIEW_STATE;\n }\n return seedState;\n}\n\n// The widget (bundled into the `/dev` entry) and the theme merge (bundled into\n// the engine index via `useTwilightInit`) import this module from two different\n// chunks, so each would otherwise get its OWN copy of the state — the widget\n// would enable a store the merge never reads. Back the state with a single\n// globalThis-keyed instance so every copy shares one source of truth. Dev-only,\n// so a global is acceptable (and lazy, so the module stays side-effect free and\n// tree-shakes out of production).\ninterface DevStoreSingleton {\n state: DevPreviewState;\n listeners: Set<() => void>;\n /** This page's own home blocks, when it is a storefront on its home page. Never saved. */\n ownBlocks: LiveBlocks | null;\n meta: DevEditorMeta;\n metaListeners: Set<() => void>;\n saveTimer: ReturnType<typeof setTimeout> | undefined;\n /** An edit that has not been sent yet. */\n dirty: boolean;\n /** A save request on its way; the next one waits for it, so saves land in order. */\n inFlight: boolean;\n /** The old localStorage copy is removed only once the file has the migrated values. */\n legacyPending: boolean;\n channel: BroadcastChannel | null;\n /** In the editor: the storefront frame's window. */\n getFrame: (() => Window | null) | null;\n /** In the frame: when the server fetched the settings this page rendered with. */\n settingsFetchedAt: number | null;\n /** Detach this copy's listeners and channel. A page keeps one copy for good; tests swap them. */\n dispose: () => void;\n}\n\nconst SINGLETON_KEY = '__twilightDevSettingsStore__';\n\nfunction singleton(): DevStoreSingleton {\n const g = globalThis as unknown as Record<string, DevStoreSingleton | undefined>;\n let s = g[SINGLETON_KEY];\n if (!s) {\n const seeded = (globalThis as Record<string, unknown>)[DEV_PREVIEW_GLOBAL] != null;\n s = {\n state: readSeed(),\n listeners: new Set(),\n ownBlocks: null,\n meta: { liveBlocks: null, saveStatus: 'idle', frameBase: undefined, settingsFetchedAt: null },\n metaListeners: new Set(),\n saveTimer: undefined,\n dirty: false,\n inFlight: false,\n legacyPending: false,\n channel: null,\n getFrame: null,\n settingsFetchedAt: null,\n dispose: () => {},\n };\n g[SINGLETON_KEY] = s;\n if (typeof window !== 'undefined') setUpBrowser(s, seeded);\n }\n return s;\n}\n\nfunction setUpBrowser(s: DevStoreSingleton, seeded: boolean): void {\n const listeners = new AbortController();\n const { signal } = listeners;\n if (!seeded) migrateLegacy(s);\n listenForOtherTabs();\n s.channel = openChannel();\n listenForFrameMessages(s, signal);\n window.addEventListener('pagehide', () => flushOnExit(s), { signal });\n s.dispose = () => {\n listeners.abort();\n s.channel?.close();\n clearTimeout(s.saveTimer);\n };\n if (isEditorFrame()) sendToEditor({ kind: 'frame-info', base: resolveStoreBase() });\n}\n\n/** Carry the old widget's settings over; its per-block patches don't map to a layout. */\nfunction migrateLegacy(s: DevStoreSingleton): void {\n try {\n const raw = window.localStorage.getItem(LEGACY_STORAGE_KEY);\n if (!raw) return;\n const legacy = normalizePreviewState(JSON.parse(raw));\n if (!legacy) return;\n s.state = { enabled: legacy.enabled, settings: legacy.settings, layout: null };\n s.legacyPending = true;\n scheduleSave(s);\n } catch {\n // Storage blocked or the old value is corrupt: nothing worth keeping.\n }\n}\n\n/** Vite's HMR client, typed locally: the engine's `ImportMeta` must not clash with `vite/client`. */\ninterface HotContext {\n on(event: string, cb: (payload: { state?: unknown; from?: unknown }) => void): void;\n}\n\n/**\n * Take a state another copy committed. Not while this copy has an edit of its\n * own waiting to be saved: that edit is newer, and saving it will tell the rest.\n */\nfunction receive(raw: unknown): void {\n const s = singleton();\n if (s.dirty || s.inFlight || s.saveTimer) return;\n const next = normalizePreviewState(raw);\n if (next && JSON.stringify(next) !== JSON.stringify(s.state)) emit(next);\n}\n\n/** Tabs in another browser hear about a save from the dev server. */\nfunction listenForOtherTabs(): void {\n const hot = (import.meta as ImportMeta & { hot?: HotContext }).hot;\n if (!hot) return;\n hot.on(DEV_PREVIEW_EVENT, (payload) => {\n if (payload?.from !== myTabId()) receive(payload?.state);\n });\n}\n\nfunction openChannel(): BroadcastChannel | null {\n if (typeof BroadcastChannel === 'undefined') return null;\n const channel = new BroadcastChannel(CHANNEL_NAME);\n channel.onmessage = ({ data }: MessageEvent<{ state?: unknown; from?: string }>) => {\n if (data && data.from !== myTabId()) receive(data.state);\n };\n return channel;\n}\n\nfunction sendToEditor(message: FrameMessage): void {\n if (isEditorFrame())\n window.parent.postMessage({ type: FRAME_MESSAGE, message }, window.location.origin);\n}\n\nfunction sendToFrame(message: FrameMessage): void {\n singleton().getFrame?.()?.postMessage({ type: FRAME_MESSAGE, message }, window.location.origin);\n}\n\nfunction reportToEditor(s: DevStoreSingleton): void {\n sendToEditor({ kind: 'frame-info', base: resolveStoreBase() });\n sendToEditor({ kind: 'live-blocks', blocks: s.ownBlocks });\n if (s.settingsFetchedAt != null)\n sendToEditor({ kind: 'settings-fetched', at: s.settingsFetchedAt });\n}\n\n/**\n * The editor ↔ frame conversation. A frame only takes requests from its own\n * parent; an editor only takes reports from the frame it shows.\n */\nfunction listenForFrameMessages(s: DevStoreSingleton, signal: AbortSignal): void {\n window.addEventListener(\n 'message',\n (event: MessageEvent) => {\n if (event.origin !== window.location.origin || event.data?.type !== FRAME_MESSAGE) return;\n const message = event.data.message as FrameMessage;\n if (window.parent !== window && event.source === window.parent) {\n answerEditor(s, message);\n return;\n }\n const frame = s.getFrame?.();\n if (frame && event.source === frame) takeFrameReport(message);\n },\n { signal }\n );\n}\n\n/** In the frame: what its editor asks for. */\nfunction answerEditor(s: DevStoreSingleton, message: FrameMessage): void {\n if (message.kind === 'request-live-blocks') reportToEditor(s);\n else if (message.kind === 'focus-block') scrollToBlock(message.index);\n else if (message.kind === 'lookup') void answerLookup(message);\n}\n\n/** In the editor: what its frame reports. */\nfunction takeFrameReport(message: FrameMessage): void {\n if (message.kind === 'lookup-result') settleLookup(message);\n else if (message.kind === 'live-blocks') setMeta({ liveBlocks: message.blocks });\n else if (message.kind === 'frame-info') setMeta({ frameBase: message.base });\n else if (message.kind === 'settings-fetched' && Number.isFinite(message.at))\n setMeta({ settingsFetchedAt: message.at });\n}\n\n/** In the frame: look the request up in the store and send back what was found, or why not. */\nasync function answerLookup(message: Extract<FrameMessage, { kind: 'lookup' }>): Promise<void> {\n const { requestId, source, query } = message;\n try {\n const { lookupInStore } = await import('./store-lookup');\n sendToEditor({ kind: 'lookup-result', requestId, items: await lookupInStore(source, query) });\n } catch (error) {\n sendToEditor({\n kind: 'lookup-result',\n requestId,\n error: error instanceof Error ? error.message : 'lookup failed',\n });\n }\n}\n\nfunction settleLookup(message: Extract<FrameMessage, { kind: 'lookup-result' }>): void {\n const pending = pendingLookups.get(message.requestId);\n if (!pending) return;\n pendingLookups.delete(message.requestId);\n clearTimeout(pending.timer);\n if (message.items) pending.resolve(message.items);\n else pending.reject(new Error(message.error ?? 'lookup failed'));\n}\n\n/**\n * In the editor's frame: bring a home block into view and flash an outline on\n * it. Dev-only editor chrome, so it styles the element directly rather than\n * through the theme's React tree. A block added a moment ago may not be in the\n * DOM yet, so look for it for a little while.\n */\nfunction scrollToBlock(index: number): void {\n const started = Date.now();\n const find = () => {\n const el = document.querySelector<HTMLElement>(`[data-home-block=\"${index}\"]`);\n if (!el) {\n if (Date.now() - started < FOCUS_WAIT_MS) requestAnimationFrame(find);\n return;\n }\n const { outline, outlineOffset, scrollMarginTop } = el.style;\n // Clear a sticky header, which would otherwise cover the block's top.\n el.style.scrollMarginTop = '80px';\n el.scrollIntoView({ behavior: 'smooth', block: 'start' });\n el.style.outline = '2px solid #0d9488';\n el.style.outlineOffset = '-2px';\n setTimeout(() => {\n el.style.outline = outline;\n el.style.outlineOffset = outlineOffset;\n el.style.scrollMarginTop = scrollMarginTop;\n }, FOCUS_FLASH_MS);\n };\n find();\n}\n\nfunction emit(next: DevPreviewState): void {\n const s = singleton();\n s.state = next;\n s.listeners.forEach((l) => l());\n}\n\nfunction setMeta(patch: Partial<DevEditorMeta>): void {\n const s = singleton();\n s.meta = { ...s.meta, ...patch };\n s.metaListeners.forEach((l) => l());\n}\n\nfunction saveRequest(s: DevStoreSingleton, keepalive = false): Promise<Response> {\n return fetch(DEV_PREVIEW_ENDPOINT, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ state: s.state, from: myTabId() }),\n keepalive,\n });\n}\n\n/** Send the current state, one request at a time; edits made meanwhile go in the next one. */\nasync function flush(s: DevStoreSingleton): Promise<void> {\n if (s.inFlight || !s.dirty) return;\n s.inFlight = true;\n s.dirty = false;\n let failed = false;\n try {\n const res = await saveRequest(s);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n if (s.legacyPending) {\n s.legacyPending = false;\n try {\n window.localStorage.removeItem(LEGACY_STORAGE_KEY);\n } catch {\n // Storage went away; the file has the values now either way.\n }\n }\n if (!s.dirty && !s.saveTimer) setMeta({ saveStatus: 'saved' });\n } catch (error) {\n // Still unsaved: another tab's state must not replace it, and leaving the\n // page still sends it. Edits made while this request was out are sent once\n // more; the failed one alone waits for the next edit, so nothing loops.\n failed = !s.dirty;\n s.dirty = true;\n setMeta({ saveStatus: 'error' });\n console.error('[twilight-react:preview] could not save twilight.preview.json', error);\n } finally {\n s.inFlight = false;\n if (!failed && s.dirty && !s.saveTimer) void flush(s);\n }\n}\n\nfunction scheduleSave(s: DevStoreSingleton): void {\n if (typeof window === 'undefined' || typeof fetch === 'undefined') return;\n s.dirty = true;\n clearTimeout(s.saveTimer);\n setMeta({ saveStatus: 'saving' });\n s.saveTimer = setTimeout(() => {\n s.saveTimer = undefined;\n void flush(s);\n }, SAVE_DELAY_MS);\n}\n\n/** Closing or reloading the editor must not drop the last edit: send it on the way out. */\nfunction flushOnExit(s: DevStoreSingleton): void {\n if (!s.dirty) return;\n clearTimeout(s.saveTimer);\n s.saveTimer = undefined;\n s.dirty = false;\n void saveRequest(s, true).catch(() => {});\n}\n\nfunction commit(next: DevPreviewState): void {\n const s = singleton();\n emit(next);\n try {\n s.channel?.postMessage({ state: next, from: myTabId() });\n } catch {\n // A value that can't be cloned: the other copies pick it up from the save instead.\n }\n scheduleSave(s);\n}\n\nfunction newBlockId(): string {\n return `b-${randomId()}`;\n}\n\n/** Home loader spelling of a twilight.json path. */\nexport function blockPath(path: string): string {\n return path.replace(/^home\\./, '');\n}\n\nfunction updateLayout(update: (layout: DevPreviewBlock[]) => DevPreviewBlock[]): void {\n const { state } = singleton();\n commit({ ...state, layout: update(state.layout ?? []) });\n}\n\n/** A new block for a twilight.json component, filled with its defaults. */\nfunction blockFor(schema: DevSchema, path: string): DevPreviewBlock {\n const component = schema.components.find((c) => c.path === path);\n const defaults = schema.blockDefaults?.[path] ?? schema.componentDefaults[path] ?? {};\n return {\n id: newBlockId(),\n path: blockPath(path),\n fields: { ...(component?.key ? { key: component.key } : {}), ...defaults },\n };\n}\n\nexport const devSettingsStore = {\n get: (): DevPreviewState => singleton().state,\n /** What the server rendered: the saved file as of this page load. */\n getServer: (): DevPreviewState => readSeed(),\n subscribe(listener: () => void): () => void {\n const s = singleton();\n s.listeners.add(listener);\n return () => {\n s.listeners.delete(listener);\n };\n },\n /** Turn overrides on, seeding any unset setting with its twilight.json default. */\n enable(schema: DevSchema): void {\n const { state } = singleton();\n commit({\n ...state,\n enabled: true,\n settings: { ...schema.settingsDefaults, ...state.settings },\n });\n },\n disable(): void {\n commit({ ...singleton().state, enabled: false });\n },\n setSetting(id: string, value: unknown): void {\n const { state } = singleton();\n commit({ ...state, settings: { ...state.settings, [id]: value } });\n },\n /** Restore every setting to its twilight.json default (keeps enabled and the layout). */\n resetSettings(schema: DevSchema): void {\n commit({ ...singleton().state, settings: { ...schema.settingsDefaults } });\n },\n\n // ── Editor ↔ frame ───────────────────────────────────────────────────────\n\n /** The editor tells the store which window is its storefront frame. */\n connectFrame(getFrame: () => Window | null): () => void {\n const s = singleton();\n s.getFrame = getFrame;\n return () => {\n if (s.getFrame === getFrame) s.getFrame = null;\n };\n },\n /** A storefront's home page reports its blocks (`null` when it leaves); in the editor's frame they go to the editor. Not saved. */\n setLiveBlocks(blocks: LiveBlocks | null): void {\n const s = singleton();\n s.ownBlocks = blocks;\n sendToEditor({ kind: 'live-blocks', blocks });\n },\n /** Ask the frame for its home page's blocks and its store base. */\n requestLiveBlocks(): void {\n sendToFrame({ kind: 'request-live-blocks' });\n },\n /**\n * In the editor: a page loaded in the frame. The fetch time the last page\n * reported says nothing about this one, and a page whose settings failed reports\n * none, so it is dropped before this page is asked for its report.\n */\n frameLoaded(): void {\n setMeta({ settingsFetchedAt: null });\n sendToFrame({ kind: 'request-live-blocks' });\n },\n /**\n * Search the dev store through the editor's frame. Rejects when there is no\n * frame, it doesn't answer in time, or the store refuses; pickers then fall\n * back to samples.\n */\n lookup(source: DevLookupSource, query: string): Promise<DevLookupItem[]> {\n const frame = singleton().getFrame?.();\n if (!frame) return Promise.reject(new Error('no storefront frame'));\n const requestId = randomId();\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n pendingLookups.delete(requestId);\n reject(new Error('the storefront did not answer'));\n }, DEV_LOOKUP_TIMEOUT_MS);\n pendingLookups.set(requestId, { resolve, reject, timer });\n sendToFrame({ kind: 'lookup', requestId, source, query });\n });\n },\n /** Scroll the editor's frame to the home block at `index`. */\n focusBlock(index: number): void {\n sendToFrame({ kind: 'focus-block', index });\n },\n /** In the frame: tell the editor when the server fetched the settings this page rendered with. */\n reportSettingsFetchedAt(at: number): void {\n const s = singleton();\n if (s.settingsFetchedAt === at) return;\n s.settingsFetchedAt = at;\n sendToEditor({ kind: 'settings-fetched', at });\n },\n getMeta: (): DevEditorMeta => singleton().meta,\n subscribeMeta(listener: () => void): () => void {\n const s = singleton();\n s.metaListeners.add(listener);\n return () => {\n s.metaListeners.delete(listener);\n };\n },\n\n // ── Home layout ──────────────────────────────────────────────────────────\n\n /**\n * Take over the home layout. Starts from the blocks the home page showed (the\n * frame's in the editor; an empty page stays empty), otherwise from every\n * twilight.json component.\n */\n customizeLayout(schema: DevSchema): void {\n const s = singleton();\n const live = s.meta.liveBlocks ?? s.ownBlocks;\n const layout: DevPreviewBlock[] =\n live !== null\n ? live\n .filter((block): block is { path: string } => typeof block.path === 'string')\n .filter((block) => block.path !== '')\n .map(({ path, ...fields }) => ({ id: newBlockId(), path: blockPath(path), fields }))\n : schema.components.map((component) => blockFor(schema, component.path));\n commit({ ...s.state, enabled: true, layout });\n },\n startEmptyLayout(): void {\n commit({ ...singleton().state, enabled: true, layout: [] });\n },\n /** Back to the store's own blocks. */\n clearLayout(): void {\n commit({ ...singleton().state, layout: null });\n },\n /** Insert a twilight.json component at `at` (default: the end); returns the new block's id. */\n addBlock(schema: DevSchema, path: string, at?: number): string {\n const block = blockFor(schema, path);\n updateLayout((layout) => {\n const next = [...layout];\n next.splice(at ?? next.length, 0, block);\n return next;\n });\n return block.id;\n },\n removeBlock(id: string): void {\n updateLayout((layout) => layout.filter((block) => block.id !== id));\n },\n duplicateBlock(id: string): void {\n updateLayout((layout) => {\n const index = layout.findIndex((block) => block.id === id);\n if (index === -1) return layout;\n const copy = { ...layout[index], id: newBlockId(), fields: { ...layout[index].fields } };\n return [...layout.slice(0, index + 1), copy, ...layout.slice(index + 1)];\n });\n },\n /** Move a block to index `to` (its position after the move). */\n moveBlock(id: string, to: number): void {\n updateLayout((layout) => {\n const from = layout.findIndex((block) => block.id === id);\n if (from === -1) return layout;\n const target = Math.max(0, Math.min(to, layout.length - 1));\n if (target === from) return layout;\n const next = [...layout];\n const [block] = next.splice(from, 1);\n next.splice(target, 0, block);\n return next;\n });\n },\n setBlockField(id: string, fieldId: string, value: unknown): void {\n updateLayout((layout) =>\n layout.map((block) =>\n block.id === id ? { ...block, fields: { ...block.fields, [fieldId]: value } } : block\n )\n );\n },\n};\n\nconst SERVER_META: DevEditorMeta = {\n liveBlocks: null,\n saveStatus: 'idle',\n frameBase: undefined,\n settingsFetchedAt: null,\n};\n\n/** The frame's blocks and store base, and the save status, for the editor. */\nexport function useDevEditorMeta(): DevEditorMeta {\n return useSyncExternalStore(\n devSettingsStore.subscribeMeta,\n devSettingsStore.getMeta,\n () => SERVER_META\n );\n}\n\n/** Raw store subscription. */\nexport function useDevSettingsState(): DevPreviewState {\n return useSyncExternalStore(\n devSettingsStore.subscribe,\n devSettingsStore.get,\n devSettingsStore.getServer\n );\n}\n\n/**\n * Overrides for SSR-rendered consumers (the theme). The server and the first\n * browser render both read the saved file, so they agree and nothing flashes.\n *\n * Which hook this is gets decided once, when the module loads: in production\n * `import.meta.env.DEV` is a static `false`, so only the empty one survives\n * bundling and the store subscription (and the whole store module, which has\n * no other prod consumer) is dead-code-eliminated. No hook is ever called\n * conditionally.\n */\nexport const useDevSettingsOverrides: () => DevPreviewState = import.meta.env.DEV\n ? useDevSettingsState\n : () => EMPTY_PREVIEW_STATE;\n\nfunction useReportSettingsFetchedAt(at: number | undefined): void {\n useEffect(() => {\n if (at != null) devSettingsStore.reportSettingsFetchedAt(at);\n }, [at]);\n}\n\n/**\n * In the editor's frame: report when the dev server fetched this page's store\n * settings, so the editor can say how old they are. A no-op in production, decided\n * once at load like {@link useDevSettingsOverrides}.\n */\nexport const useDevReportSettingsFetchedAt: (at: number | undefined) => void = import.meta.env.DEV\n ? useReportSettingsFetchedAt\n : () => {};\n\n/** A rendered home block; `__dev_id` keys a dev-layout block across reorders. */\nexport type DevHomeBlock<T> = T & { __dev_id?: string };\n\n/**\n * Whether a list in a block's fields gained, lost or reordered items. Blocks\n * often hand their items to a web component that takes them once when it\n * starts (a slider moves its slides into its own track), so such a change\n * never reaches the page until the block mounts again. Editing an item's\n * values is not one: the nodes stay put and update in place.\n */\nexport function listsReshaped(\n before: Record<string, unknown>,\n after: Record<string, unknown>\n): boolean {\n for (const key of new Set([...Object.keys(before), ...Object.keys(after)])) {\n const a = before[key];\n const b = after[key];\n if (!Array.isArray(a) && !Array.isArray(b)) continue;\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return true;\n const aItems = a.map((item) => JSON.stringify(item));\n const bItems = b.map((item) => JSON.stringify(item));\n const moved = aItems.some((item, i) => item !== bItems[i]);\n if (moved && [...aItems].sort().join('\\n') === [...bItems].sort().join('\\n')) return true;\n }\n return false;\n}\n\n/**\n * The home page's blocks: the dev layout when one is saved and enabled, else\n * the store's own blocks untouched. Also reports the store's blocks to the\n * editor so \"Customize\" can start from what the page showed, and withdraws\n * them when the page goes.\n *\n * Same production story as {@link useDevSettingsOverrides}: chosen once at\n * module load, so production keeps only the passthrough.\n */\nfunction useDevLayoutBlocks<T extends { path?: string }>(components: T[]): DevHomeBlock<T>[] {\n const overrides = useDevSettingsState();\n // Per block: the fields last rendered, and how often its lists were reshaped.\n const seen = useRef(new Map<string, { fields: Record<string, unknown>; mounts: number }>());\n useEffect(() => {\n devSettingsStore.setLiveBlocks(components);\n return () => devSettingsStore.setLiveBlocks(null);\n }, [components]);\n return useMemo(() => {\n if (!overrides.enabled || !overrides.layout) return components;\n return overrides.layout.map((block) => {\n const last = seen.current.get(block.id);\n const mounts =\n (last?.mounts ?? 0) + (last && listsReshaped(last.fields, block.fields) ? 1 : 0);\n seen.current.set(block.id, { fields: block.fields, mounts });\n // A new key mounts the block again, so a reshaped list reaches the page.\n const devId = mounts ? `${block.id}~${mounts}` : block.id;\n return { ...block.fields, path: block.path, __dev_id: devId } as DevHomeBlock<T>;\n });\n }, [components, overrides]);\n}\n\nexport const useDevHomeBlocks: <T extends { path?: string }>(components: T[]) => DevHomeBlock<T>[] =\n import.meta.env.DEV ? useDevLayoutBlocks : (components) => components;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/dev/dev-settings-store.ts"],"names":["block"],"mappings":"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","file":"chunk-AEM5UEH6.js","sourcesContent":["/**\n * Client-side store for the dev editor: theme-setting overrides and a dev-owned\n * home layout. Saved to `twilight.preview.json` through the dev server (see\n * `twilight-schema.plugin.ts`), not to localStorage, for three reasons: the\n * server render can read a file, so the page hydrates with the edited layout\n * instead of flashing the store's; the state survives a port or browser\n * change; and the developer can open, diff or delete it.\n *\n * The saved state reaches this module through `virtual:twilight/schema`, which\n * the root route imports on both sides before anything renders and which puts\n * it on `globalThis[DEV_PREVIEW_GLOBAL]`. Server snapshots read that value\n * (the server's modules are re-run after each save); the browser copies it once\n * and then owns the state.\n *\n * The theme editor (`/__twilight/editor`) frames the storefront, so two copies\n * of this store run side by side. Edits reach every copy on the origin at once\n * over a `BroadcastChannel` (the file save is debounced), and only the copy\n * that made an edit saves it. Everything else between an editor and its frame\n * (the home page's blocks, the store base, scroll-to-block) goes by\n * `postMessage` to that one window, so another storefront tab never answers.\n */\n\nimport { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';\nimport {\n DEV_LOOKUP_TIMEOUT_MS,\n DEV_PREVIEW_ENDPOINT,\n DEV_PREVIEW_EVENT,\n DEV_PREVIEW_GLOBAL,\n EMPTY_PREVIEW_STATE,\n isEditorFrame,\n normalizePreviewState,\n type DevLookupItem,\n type DevLookupSource,\n type DevPreviewBlock,\n type DevPreviewState,\n type DevSchema,\n} from './schema-types';\nimport { resolveStoreBase } from '../utils/store-identity';\n\nexport type DevSettingsState = DevPreviewState;\nexport type DevSaveStatus = 'idle' | 'saving' | 'saved' | 'error';\ntype LiveBlocks = { path?: string }[];\n\n/** Where the old localStorage-backed widget kept its state; migrated once. */\nconst LEGACY_STORAGE_KEY = 'twilight:dev-settings';\n/** Batch keystrokes into one write. */\nconst SAVE_DELAY_MS = 250;\n/** Same-browser channel every copy of the store listens on, for edits. */\nconst CHANNEL_NAME = 'twilight:preview';\n/** Envelope type of the editor ↔ frame `postMessage`s. */\nconst FRAME_MESSAGE = 'twilight:editor';\n/** How long the frame keeps looking for a block that is still rendering (just added, say). */\nconst FOCUS_WAIT_MS = 2000;\nconst FOCUS_FLASH_MS = 1200;\n\n/** Editor ↔ the storefront it frames. */\ntype FrameMessage =\n | { kind: 'live-blocks'; blocks: LiveBlocks | null }\n | { kind: 'frame-info'; base: string | null }\n | { kind: 'settings-fetched'; at: number }\n | { kind: 'request-live-blocks' }\n | { kind: 'focus-block'; index: number }\n | { kind: 'lookup'; requestId: string; source: DevLookupSource; query: string }\n | { kind: 'lookup-result'; requestId: string; items?: DevLookupItem[]; error?: string };\n\ninterface PendingLookup {\n resolve: (items: DevLookupItem[]) => void;\n reject: (error: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n}\nconst pendingLookups = new Map<string, PendingLookup>();\n\n/** What the editor shows besides the saved state. */\nexport interface DevEditorMeta {\n /** The blocks the framed home page shows; `null` when it is not on the home page. */\n liveBlocks: LiveBlocks | null;\n saveStatus: DevSaveStatus;\n /** The frame's store segment; `undefined` until the frame has said. */\n frameBase: string | null | undefined;\n /**\n * When the dev server last asked the API for the frame's store settings (epoch\n * ms), which it reuses for a while (see `api/dev-settings-cache.ts`); `null`\n * until the frame says.\n */\n settingsFetchedAt: number | null;\n}\n\n/**\n * A short random hex id. `getRandomValues`, not `randomUUID`: the latter only\n * exists in secure contexts, and the dev server may be opened on a LAN address.\n */\nfunction randomId(bytes = 6): string {\n const values = globalThis.crypto.getRandomValues(new Uint8Array(bytes));\n return Array.from(values, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nlet tabId: string | undefined;\n\n/**\n * Sent with every save so this tab can ignore its own broadcast. Made on first\n * use, never at module load: Cloudflare Workers refuse random values in global\n * scope, and this module is in the worker bundle (its use is dev-only, its\n * top level is not).\n */\nfunction myTabId(): string {\n tabId ??= randomId();\n return tabId;\n}\n\nlet seedSource: unknown;\nlet seedState: DevPreviewState = EMPTY_PREVIEW_STATE;\n\n/** The saved file as this page loaded it, normalized once per value so snapshots keep their identity. */\nfunction readSeed(): DevPreviewState {\n const raw = (globalThis as Record<string, unknown>)[DEV_PREVIEW_GLOBAL];\n if (raw !== seedSource) {\n seedSource = raw;\n seedState = normalizePreviewState(raw) ?? EMPTY_PREVIEW_STATE;\n }\n return seedState;\n}\n\n// The widget (bundled into the `/dev` entry) and the theme merge (bundled into\n// the engine index via `useTwilightInit`) import this module from two different\n// chunks, so each would otherwise get its OWN copy of the state — the widget\n// would enable a store the merge never reads. Back the state with a single\n// globalThis-keyed instance so every copy shares one source of truth. Dev-only,\n// so a global is acceptable (and lazy, so the module stays side-effect free and\n// tree-shakes out of production).\ninterface DevStoreSingleton {\n state: DevPreviewState;\n listeners: Set<() => void>;\n /** This page's own home blocks, when it is a storefront on its home page. Never saved. */\n ownBlocks: LiveBlocks | null;\n meta: DevEditorMeta;\n metaListeners: Set<() => void>;\n saveTimer: ReturnType<typeof setTimeout> | undefined;\n /** An edit that has not been sent yet. */\n dirty: boolean;\n /** A save request on its way; the next one waits for it, so saves land in order. */\n inFlight: boolean;\n /** The old localStorage copy is removed only once the file has the migrated values. */\n legacyPending: boolean;\n channel: BroadcastChannel | null;\n /** In the editor: the storefront frame's window. */\n getFrame: (() => Window | null) | null;\n /** In the frame: when the server fetched the settings this page rendered with. */\n settingsFetchedAt: number | null;\n /** Detach this copy's listeners and channel. A page keeps one copy for good; tests swap them. */\n dispose: () => void;\n}\n\nconst SINGLETON_KEY = '__twilightDevSettingsStore__';\n\nfunction singleton(): DevStoreSingleton {\n const g = globalThis as unknown as Record<string, DevStoreSingleton | undefined>;\n let s = g[SINGLETON_KEY];\n if (!s) {\n const seeded = (globalThis as Record<string, unknown>)[DEV_PREVIEW_GLOBAL] != null;\n s = {\n state: readSeed(),\n listeners: new Set(),\n ownBlocks: null,\n meta: { liveBlocks: null, saveStatus: 'idle', frameBase: undefined, settingsFetchedAt: null },\n metaListeners: new Set(),\n saveTimer: undefined,\n dirty: false,\n inFlight: false,\n legacyPending: false,\n channel: null,\n getFrame: null,\n settingsFetchedAt: null,\n dispose: () => {},\n };\n g[SINGLETON_KEY] = s;\n if (typeof window !== 'undefined') setUpBrowser(s, seeded);\n }\n return s;\n}\n\nfunction setUpBrowser(s: DevStoreSingleton, seeded: boolean): void {\n const listeners = new AbortController();\n const { signal } = listeners;\n if (!seeded) migrateLegacy(s);\n listenForOtherTabs();\n s.channel = openChannel();\n listenForFrameMessages(s, signal);\n window.addEventListener('pagehide', () => flushOnExit(s), { signal });\n s.dispose = () => {\n listeners.abort();\n s.channel?.close();\n clearTimeout(s.saveTimer);\n };\n if (isEditorFrame()) sendToEditor({ kind: 'frame-info', base: resolveStoreBase() });\n}\n\n/** Carry the old widget's settings over; its per-block patches don't map to a layout. */\nfunction migrateLegacy(s: DevStoreSingleton): void {\n try {\n const raw = window.localStorage.getItem(LEGACY_STORAGE_KEY);\n if (!raw) return;\n const legacy = normalizePreviewState(JSON.parse(raw));\n if (!legacy) return;\n s.state = { enabled: legacy.enabled, settings: legacy.settings, layout: null };\n s.legacyPending = true;\n scheduleSave(s);\n } catch {\n // Storage blocked or the old value is corrupt: nothing worth keeping.\n }\n}\n\n/** Vite's HMR client, typed locally: the engine's `ImportMeta` must not clash with `vite/client`. */\ninterface HotContext {\n on(event: string, cb: (payload: { state?: unknown; from?: unknown }) => void): void;\n}\n\n/**\n * Take a state another copy committed. Not while this copy has an edit of its\n * own waiting to be saved: that edit is newer, and saving it will tell the rest.\n */\nfunction receive(raw: unknown): void {\n const s = singleton();\n if (s.dirty || s.inFlight || s.saveTimer) return;\n const next = normalizePreviewState(raw);\n if (next && JSON.stringify(next) !== JSON.stringify(s.state)) emit(next);\n}\n\n/** Tabs in another browser hear about a save from the dev server. */\nfunction listenForOtherTabs(): void {\n const hot = (import.meta as ImportMeta & { hot?: HotContext }).hot;\n if (!hot) return;\n hot.on(DEV_PREVIEW_EVENT, (payload) => {\n if (payload?.from !== myTabId()) receive(payload?.state);\n });\n}\n\nfunction openChannel(): BroadcastChannel | null {\n if (typeof BroadcastChannel === 'undefined') return null;\n const channel = new BroadcastChannel(CHANNEL_NAME);\n channel.onmessage = ({ data }: MessageEvent<{ state?: unknown; from?: string }>) => {\n if (data && data.from !== myTabId()) receive(data.state);\n };\n return channel;\n}\n\nfunction sendToEditor(message: FrameMessage): void {\n if (isEditorFrame())\n window.parent.postMessage({ type: FRAME_MESSAGE, message }, window.location.origin);\n}\n\nfunction sendToFrame(message: FrameMessage): void {\n singleton().getFrame?.()?.postMessage({ type: FRAME_MESSAGE, message }, window.location.origin);\n}\n\nfunction reportToEditor(s: DevStoreSingleton): void {\n sendToEditor({ kind: 'frame-info', base: resolveStoreBase() });\n sendToEditor({ kind: 'live-blocks', blocks: s.ownBlocks });\n if (s.settingsFetchedAt != null)\n sendToEditor({ kind: 'settings-fetched', at: s.settingsFetchedAt });\n}\n\n/**\n * The editor ↔ frame conversation. A frame only takes requests from its own\n * parent; an editor only takes reports from the frame it shows.\n */\nfunction listenForFrameMessages(s: DevStoreSingleton, signal: AbortSignal): void {\n window.addEventListener(\n 'message',\n (event: MessageEvent) => {\n if (event.origin !== window.location.origin || event.data?.type !== FRAME_MESSAGE) return;\n const message = event.data.message as FrameMessage;\n if (window.parent !== window && event.source === window.parent) {\n answerEditor(s, message);\n return;\n }\n const frame = s.getFrame?.();\n if (frame && event.source === frame) takeFrameReport(message);\n },\n { signal }\n );\n}\n\n/** In the frame: what its editor asks for. */\nfunction answerEditor(s: DevStoreSingleton, message: FrameMessage): void {\n if (message.kind === 'request-live-blocks') reportToEditor(s);\n else if (message.kind === 'focus-block') scrollToBlock(message.index);\n else if (message.kind === 'lookup') void answerLookup(message);\n}\n\n/** In the editor: what its frame reports. */\nfunction takeFrameReport(message: FrameMessage): void {\n if (message.kind === 'lookup-result') settleLookup(message);\n else if (message.kind === 'live-blocks') setMeta({ liveBlocks: message.blocks });\n else if (message.kind === 'frame-info') setMeta({ frameBase: message.base });\n else if (message.kind === 'settings-fetched' && Number.isFinite(message.at))\n setMeta({ settingsFetchedAt: message.at });\n}\n\n/** In the frame: look the request up in the store and send back what was found, or why not. */\nasync function answerLookup(message: Extract<FrameMessage, { kind: 'lookup' }>): Promise<void> {\n const { requestId, source, query } = message;\n try {\n const { lookupInStore } = await import('./store-lookup');\n sendToEditor({ kind: 'lookup-result', requestId, items: await lookupInStore(source, query) });\n } catch (error) {\n sendToEditor({\n kind: 'lookup-result',\n requestId,\n error: error instanceof Error ? error.message : 'lookup failed',\n });\n }\n}\n\nfunction settleLookup(message: Extract<FrameMessage, { kind: 'lookup-result' }>): void {\n const pending = pendingLookups.get(message.requestId);\n if (!pending) return;\n pendingLookups.delete(message.requestId);\n clearTimeout(pending.timer);\n if (message.items) pending.resolve(message.items);\n else pending.reject(new Error(message.error ?? 'lookup failed'));\n}\n\n/**\n * In the editor's frame: bring a home block into view and flash an outline on\n * it. Dev-only editor chrome, so it styles the element directly rather than\n * through the theme's React tree. A block added a moment ago may not be in the\n * DOM yet, so look for it for a little while.\n */\nfunction scrollToBlock(index: number): void {\n const started = Date.now();\n const find = () => {\n const el = document.querySelector<HTMLElement>(`[data-home-block=\"${index}\"]`);\n if (!el) {\n if (Date.now() - started < FOCUS_WAIT_MS) requestAnimationFrame(find);\n return;\n }\n const { outline, outlineOffset, scrollMarginTop } = el.style;\n // Clear a sticky header, which would otherwise cover the block's top.\n el.style.scrollMarginTop = '80px';\n el.scrollIntoView({ behavior: 'smooth', block: 'start' });\n el.style.outline = '2px solid #0d9488';\n el.style.outlineOffset = '-2px';\n setTimeout(() => {\n el.style.outline = outline;\n el.style.outlineOffset = outlineOffset;\n el.style.scrollMarginTop = scrollMarginTop;\n }, FOCUS_FLASH_MS);\n };\n find();\n}\n\nfunction emit(next: DevPreviewState): void {\n const s = singleton();\n s.state = next;\n s.listeners.forEach((l) => l());\n}\n\nfunction setMeta(patch: Partial<DevEditorMeta>): void {\n const s = singleton();\n s.meta = { ...s.meta, ...patch };\n s.metaListeners.forEach((l) => l());\n}\n\nfunction saveRequest(s: DevStoreSingleton, keepalive = false): Promise<Response> {\n return fetch(DEV_PREVIEW_ENDPOINT, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ state: s.state, from: myTabId() }),\n keepalive,\n });\n}\n\n/** Send the current state, one request at a time; edits made meanwhile go in the next one. */\nasync function flush(s: DevStoreSingleton): Promise<void> {\n if (s.inFlight || !s.dirty) return;\n s.inFlight = true;\n s.dirty = false;\n let failed = false;\n try {\n const res = await saveRequest(s);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n if (s.legacyPending) {\n s.legacyPending = false;\n try {\n window.localStorage.removeItem(LEGACY_STORAGE_KEY);\n } catch {\n // Storage went away; the file has the values now either way.\n }\n }\n if (!s.dirty && !s.saveTimer) setMeta({ saveStatus: 'saved' });\n } catch (error) {\n // Still unsaved: another tab's state must not replace it, and leaving the\n // page still sends it. Edits made while this request was out are sent once\n // more; the failed one alone waits for the next edit, so nothing loops.\n failed = !s.dirty;\n s.dirty = true;\n setMeta({ saveStatus: 'error' });\n console.error('[twilight-react:preview] could not save twilight.preview.json', error);\n } finally {\n s.inFlight = false;\n if (!failed && s.dirty && !s.saveTimer) void flush(s);\n }\n}\n\nfunction scheduleSave(s: DevStoreSingleton): void {\n if (typeof window === 'undefined' || typeof fetch === 'undefined') return;\n s.dirty = true;\n clearTimeout(s.saveTimer);\n setMeta({ saveStatus: 'saving' });\n s.saveTimer = setTimeout(() => {\n s.saveTimer = undefined;\n void flush(s);\n }, SAVE_DELAY_MS);\n}\n\n/** Closing or reloading the editor must not drop the last edit: send it on the way out. */\nfunction flushOnExit(s: DevStoreSingleton): void {\n if (!s.dirty) return;\n clearTimeout(s.saveTimer);\n s.saveTimer = undefined;\n s.dirty = false;\n void saveRequest(s, true).catch(() => {});\n}\n\nfunction commit(next: DevPreviewState): void {\n const s = singleton();\n emit(next);\n try {\n s.channel?.postMessage({ state: next, from: myTabId() });\n } catch {\n // A value that can't be cloned: the other copies pick it up from the save instead.\n }\n scheduleSave(s);\n}\n\nfunction newBlockId(): string {\n return `b-${randomId()}`;\n}\n\n/** Home loader spelling of a twilight.json path. */\nexport function blockPath(path: string): string {\n return path.replace(/^home\\./, '');\n}\n\nfunction updateLayout(update: (layout: DevPreviewBlock[]) => DevPreviewBlock[]): void {\n const { state } = singleton();\n commit({ ...state, layout: update(state.layout ?? []) });\n}\n\n/** A new block for a twilight.json component, filled with its defaults. */\nfunction blockFor(schema: DevSchema, path: string): DevPreviewBlock {\n const component = schema.components.find((c) => c.path === path);\n const defaults = schema.blockDefaults?.[path] ?? schema.componentDefaults[path] ?? {};\n return {\n id: newBlockId(),\n path: blockPath(path),\n fields: { ...(component?.key ? { key: component.key } : {}), ...defaults },\n };\n}\n\nexport const devSettingsStore = {\n get: (): DevPreviewState => singleton().state,\n /** What the server rendered: the saved file as of this page load. */\n getServer: (): DevPreviewState => readSeed(),\n subscribe(listener: () => void): () => void {\n const s = singleton();\n s.listeners.add(listener);\n return () => {\n s.listeners.delete(listener);\n };\n },\n /** Turn overrides on, seeding any unset setting with its twilight.json default. */\n enable(schema: DevSchema): void {\n const { state } = singleton();\n commit({\n ...state,\n enabled: true,\n settings: { ...schema.settingsDefaults, ...state.settings },\n });\n },\n disable(): void {\n commit({ ...singleton().state, enabled: false });\n },\n setSetting(id: string, value: unknown): void {\n const { state } = singleton();\n commit({ ...state, settings: { ...state.settings, [id]: value } });\n },\n /** Restore every setting to its twilight.json default (keeps enabled and the layout). */\n resetSettings(schema: DevSchema): void {\n commit({ ...singleton().state, settings: { ...schema.settingsDefaults } });\n },\n\n // ── Editor ↔ frame ───────────────────────────────────────────────────────\n\n /** The editor tells the store which window is its storefront frame. */\n connectFrame(getFrame: () => Window | null): () => void {\n const s = singleton();\n s.getFrame = getFrame;\n return () => {\n if (s.getFrame === getFrame) s.getFrame = null;\n };\n },\n /** A storefront's home page reports its blocks (`null` when it leaves); in the editor's frame they go to the editor. Not saved. */\n setLiveBlocks(blocks: LiveBlocks | null): void {\n const s = singleton();\n s.ownBlocks = blocks;\n sendToEditor({ kind: 'live-blocks', blocks });\n },\n /** Ask the frame for its home page's blocks and its store base. */\n requestLiveBlocks(): void {\n sendToFrame({ kind: 'request-live-blocks' });\n },\n /**\n * In the editor: a page loaded in the frame. The fetch time the last page\n * reported says nothing about this one, and a page whose settings failed reports\n * none, so it is dropped before this page is asked for its report.\n */\n frameLoaded(): void {\n setMeta({ settingsFetchedAt: null });\n sendToFrame({ kind: 'request-live-blocks' });\n },\n /**\n * Search the dev store through the editor's frame. Rejects when there is no\n * frame, it doesn't answer in time, or the store refuses; pickers then fall\n * back to samples.\n */\n lookup(source: DevLookupSource, query: string): Promise<DevLookupItem[]> {\n const frame = singleton().getFrame?.();\n if (!frame) return Promise.reject(new Error('no storefront frame'));\n const requestId = randomId();\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n pendingLookups.delete(requestId);\n reject(new Error('the storefront did not answer'));\n }, DEV_LOOKUP_TIMEOUT_MS);\n pendingLookups.set(requestId, { resolve, reject, timer });\n sendToFrame({ kind: 'lookup', requestId, source, query });\n });\n },\n /** Scroll the editor's frame to the home block at `index`. */\n focusBlock(index: number): void {\n sendToFrame({ kind: 'focus-block', index });\n },\n /** In the frame: tell the editor when the server fetched the settings this page rendered with. */\n reportSettingsFetchedAt(at: number): void {\n const s = singleton();\n if (s.settingsFetchedAt === at) return;\n s.settingsFetchedAt = at;\n sendToEditor({ kind: 'settings-fetched', at });\n },\n getMeta: (): DevEditorMeta => singleton().meta,\n subscribeMeta(listener: () => void): () => void {\n const s = singleton();\n s.metaListeners.add(listener);\n return () => {\n s.metaListeners.delete(listener);\n };\n },\n\n // ── Home layout ──────────────────────────────────────────────────────────\n\n /**\n * Take over the home layout. Starts from the blocks the home page showed (the\n * frame's in the editor; an empty page stays empty), otherwise from every\n * twilight.json component.\n */\n customizeLayout(schema: DevSchema): void {\n const s = singleton();\n const live = s.meta.liveBlocks ?? s.ownBlocks;\n const layout: DevPreviewBlock[] =\n live !== null\n ? live\n .filter((block): block is { path: string } => typeof block.path === 'string')\n .filter((block) => block.path !== '')\n .map(({ path, ...fields }) => ({ id: newBlockId(), path: blockPath(path), fields }))\n : schema.components.map((component) => blockFor(schema, component.path));\n commit({ ...s.state, enabled: true, layout });\n },\n startEmptyLayout(): void {\n commit({ ...singleton().state, enabled: true, layout: [] });\n },\n /** Back to the store's own blocks. */\n clearLayout(): void {\n commit({ ...singleton().state, layout: null });\n },\n /** Insert a twilight.json component at `at` (default: the end); returns the new block's id. */\n addBlock(schema: DevSchema, path: string, at?: number): string {\n const block = blockFor(schema, path);\n updateLayout((layout) => {\n const next = [...layout];\n next.splice(at ?? next.length, 0, block);\n return next;\n });\n return block.id;\n },\n removeBlock(id: string): void {\n updateLayout((layout) => layout.filter((block) => block.id !== id));\n },\n duplicateBlock(id: string): void {\n updateLayout((layout) => {\n const index = layout.findIndex((block) => block.id === id);\n if (index === -1) return layout;\n const copy = { ...layout[index], id: newBlockId(), fields: { ...layout[index].fields } };\n return [...layout.slice(0, index + 1), copy, ...layout.slice(index + 1)];\n });\n },\n /** Move a block to index `to` (its position after the move). */\n moveBlock(id: string, to: number): void {\n updateLayout((layout) => {\n const from = layout.findIndex((block) => block.id === id);\n if (from === -1) return layout;\n const target = Math.max(0, Math.min(to, layout.length - 1));\n if (target === from) return layout;\n const next = [...layout];\n const [block] = next.splice(from, 1);\n next.splice(target, 0, block);\n return next;\n });\n },\n setBlockField(id: string, fieldId: string, value: unknown): void {\n updateLayout((layout) =>\n layout.map((block) =>\n block.id === id ? { ...block, fields: { ...block.fields, [fieldId]: value } } : block\n )\n );\n },\n};\n\nconst SERVER_META: DevEditorMeta = {\n liveBlocks: null,\n saveStatus: 'idle',\n frameBase: undefined,\n settingsFetchedAt: null,\n};\n\n/** The frame's blocks and store base, and the save status, for the editor. */\nexport function useDevEditorMeta(): DevEditorMeta {\n return useSyncExternalStore(\n devSettingsStore.subscribeMeta,\n devSettingsStore.getMeta,\n () => SERVER_META\n );\n}\n\n/** Raw store subscription. */\nexport function useDevSettingsState(): DevPreviewState {\n return useSyncExternalStore(\n devSettingsStore.subscribe,\n devSettingsStore.get,\n devSettingsStore.getServer\n );\n}\n\n/**\n * Overrides for SSR-rendered consumers (the theme). The server and the first\n * browser render both read the saved file, so they agree and nothing flashes.\n *\n * Which hook this is gets decided once, when the module loads: in production\n * `import.meta.env.DEV` is a static `false`, so only the empty one survives\n * bundling and the store subscription (and the whole store module, which has\n * no other prod consumer) is dead-code-eliminated. No hook is ever called\n * conditionally.\n */\nexport const useDevSettingsOverrides: () => DevPreviewState = import.meta.env.DEV\n ? useDevSettingsState\n : () => EMPTY_PREVIEW_STATE;\n\nfunction useReportSettingsFetchedAt(at: number | undefined): void {\n useEffect(() => {\n if (at != null) devSettingsStore.reportSettingsFetchedAt(at);\n }, [at]);\n}\n\n/**\n * In the editor's frame: report when the dev server fetched this page's store\n * settings, so the editor can say how old they are. A no-op in production, decided\n * once at load like {@link useDevSettingsOverrides}.\n */\nexport const useDevReportSettingsFetchedAt: (at: number | undefined) => void = import.meta.env.DEV\n ? useReportSettingsFetchedAt\n : () => {};\n\n/** A rendered home block; `__dev_id` keys a dev-layout block across reorders. */\nexport type DevHomeBlock<T> = T & { __dev_id?: string };\n\n/**\n * Whether a list in a block's fields gained, lost or reordered items. Blocks\n * often hand their items to a web component that takes them once when it\n * starts (a slider moves its slides into its own track), so such a change\n * never reaches the page until the block mounts again. Editing an item's\n * values is not one: the nodes stay put and update in place.\n */\nexport function listsReshaped(\n before: Record<string, unknown>,\n after: Record<string, unknown>\n): boolean {\n for (const key of new Set([...Object.keys(before), ...Object.keys(after)])) {\n const a = before[key];\n const b = after[key];\n if (!Array.isArray(a) && !Array.isArray(b)) continue;\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return true;\n const aItems = a.map((item) => JSON.stringify(item));\n const bItems = b.map((item) => JSON.stringify(item));\n const moved = aItems.some((item, i) => item !== bItems[i]);\n if (moved && [...aItems].sort().join('\\n') === [...bItems].sort().join('\\n')) return true;\n }\n return false;\n}\n\n/**\n * The home page's blocks: the dev layout when one is saved and enabled, else\n * the store's own blocks untouched. Also reports the store's blocks to the\n * editor so \"Customize\" can start from what the page showed, and withdraws\n * them when the page goes.\n *\n * Same production story as {@link useDevSettingsOverrides}: chosen once at\n * module load, so production keeps only the passthrough.\n */\nfunction useDevLayoutBlocks<T extends { path?: string }>(components: T[]): DevHomeBlock<T>[] {\n const overrides = useDevSettingsState();\n // Per block: the fields last rendered, and how often its lists were reshaped.\n const seen = useRef(new Map<string, { fields: Record<string, unknown>; mounts: number }>());\n useEffect(() => {\n devSettingsStore.setLiveBlocks(components);\n return () => devSettingsStore.setLiveBlocks(null);\n }, [components]);\n return useMemo(() => {\n if (!overrides.enabled || !overrides.layout) return components;\n return overrides.layout.map((block) => {\n const last = seen.current.get(block.id);\n const mounts =\n (last?.mounts ?? 0) + (last && listsReshaped(last.fields, block.fields) ? 1 : 0);\n seen.current.set(block.id, { fields: block.fields, mounts });\n // A new key mounts the block again, so a reshaped list reaches the page.\n const devId = mounts ? `${block.id}~${mounts}` : block.id;\n return { ...block.fields, path: block.path, __dev_id: devId } as DevHomeBlock<T>;\n });\n }, [components, overrides]);\n}\n\nexport const useDevHomeBlocks: <T extends { path?: string }>(components: T[]) => DevHomeBlock<T>[] =\n import.meta.env.DEV ? useDevLayoutBlocks : (components) => components;\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { api } from './chunk-
|
|
1
|
+
import { api } from './chunk-UXJAZ5JP.js';
|
|
2
2
|
import { queryOptions } from '@tanstack/react-query';
|
|
3
3
|
|
|
4
4
|
var apps = {
|
|
@@ -40,5 +40,5 @@ var apps = {
|
|
|
40
40
|
};
|
|
41
41
|
|
|
42
42
|
export { apps };
|
|
43
|
-
//# sourceMappingURL=chunk-
|
|
44
|
-
//# sourceMappingURL=chunk-
|
|
43
|
+
//# sourceMappingURL=chunk-ATL7CYF2.js.map
|
|
44
|
+
//# sourceMappingURL=chunk-ATL7CYF2.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api/apps.ts"],"names":[],"mappings":";;;AAmCO,IAAM,IAAA,GAAO;AAAA;AAAA;AAAA;AAAA;AAAA,EAKlB,UAAU,YAAmC;AAC3C,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CACpB,GAAA,CAAI,eAAA,EAAiB,EAAE,OAAA,EAAS,IAAA,EAAM,CAAA,CACtC,IAAA,EAA8B;AACjC,IAAA,OAAO,QAAQ,EAAC;AAAA,EAClB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,YAAkC;AAC1C,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CACpB,GAAA,CAAI,wBAAA,EAA0B,EAAE,OAAA,EAAS,IAAA,EAAM,CAAA,CAC/C,IAAA,EAAsC;AACzC,IAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,IAAA,IAAQ,EAAC,EAAE;AAAA,EAClC,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,QAAA,EAAU,MACR,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,MAAA,EAAQ,UAAU,CAAA;AAAA,MAC7B,OAAA,EAAS,MAAM,IAAA,CAAK,QAAA,EAAS;AAAA;AAAA,MAE7B,SAAA,EAAW,QAAA;AAAA;AAAA;AAAA;AAAA,MAIX,KAAA,EAAO;AAAA,KACR,CAAA;AAAA,IAEH,QAAA,EAAU,MACR,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,MAAA,EAAQ,UAAU,CAAA;AAAA,MAC7B,OAAA,EAAS,MAAM,IAAA,CAAK,QAAA,EAAS;AAAA;AAAA,MAE7B,SAAA,EAAW,QAAA;AAAA,MACX,KAAA,EAAO;AAAA,KACR;AAAA;AAEP","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/api/apps.ts"],"names":[],"mappings":";;;AAmCO,IAAM,IAAA,GAAO;AAAA;AAAA;AAAA;AAAA;AAAA,EAKlB,UAAU,YAAmC;AAC3C,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CACpB,GAAA,CAAI,eAAA,EAAiB,EAAE,OAAA,EAAS,IAAA,EAAM,CAAA,CACtC,IAAA,EAA8B;AACjC,IAAA,OAAO,QAAQ,EAAC;AAAA,EAClB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,YAAkC;AAC1C,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CACpB,GAAA,CAAI,wBAAA,EAA0B,EAAE,OAAA,EAAS,IAAA,EAAM,CAAA,CAC/C,IAAA,EAAsC;AACzC,IAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,IAAA,IAAQ,EAAC,EAAE;AAAA,EAClC,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,QAAA,EAAU,MACR,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,MAAA,EAAQ,UAAU,CAAA;AAAA,MAC7B,OAAA,EAAS,MAAM,IAAA,CAAK,QAAA,EAAS;AAAA;AAAA,MAE7B,SAAA,EAAW,QAAA;AAAA;AAAA;AAAA;AAAA,MAIX,KAAA,EAAO;AAAA,KACR,CAAA;AAAA,IAEH,QAAA,EAAU,MACR,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,MAAA,EAAQ,UAAU,CAAA;AAAA,MAC7B,OAAA,EAAS,MAAM,IAAA,CAAK,QAAA,EAAS;AAAA;AAAA,MAE7B,SAAA,EAAW,QAAA;AAAA,MACX,KAAA,EAAO;AAAA,KACR;AAAA;AAEP","file":"chunk-ATL7CYF2.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api } from './client';\n\nexport interface AppSnippetRow {\n place: string;\n content: string;\n url?: string | null;\n /**\n * Raw snippet id, emitted as `data-snippet-id`. Present only on CDN rows — the\n * inline branch of the backend's snippet parser omits the key entirely.\n */\n id?: number;\n /** `{{customer.x}}` placeholders in `content` to substitute from SDK config `user.*` keys. */\n customer_parameters?: string[];\n}\n\nexport interface AppSnippet {\n service: string;\n app_id: string;\n /** Encoded app id (`getRouteKey()`): the scope id its snippets bind to via `data-scope-id`,\n * and its settings-bucket key. Absent on payloads predating the settings API. */\n id?: string;\n app_slug: string;\n status: string;\n snippets: AppSnippetRow[];\n}\n\n/**\n * Per-app public `app.*` buckets for CDN snippets, keyed by encoded app id (== `AppSnippet.id`,\n * the `Salla.appScope` scope id). One isolated bucket per app; reads within a scope are bare `app.*`.\n */\nexport interface AppSettings {\n apps: Record<string, Record<string, unknown>>;\n}\n\nexport const apps = {\n /**\n * Installed apps' snippets (scripts/HTML to inject). Timeout-bounded because it's awaited in\n * rootBeforeLoad (SSR/TTFB): a slow response degrades to no CDN tags, never stalls the page.\n */\n snippets: async (): Promise<AppSnippet[]> => {\n const { data } = await api\n .get('apps/snippets', { timeout: 2500 })\n .json<{ data?: AppSnippet[] }>();\n return data ?? [];\n },\n\n /**\n * Per-app public `app.*` buckets, keyed by encoded app id. Timeout-bounded (SSR-awaited):\n * a slow response degrades to empty buckets (fail-open), never strands injection.\n */\n settings: async (): Promise<AppSettings> => {\n const { data } = await api\n .get('apps/snippets/settings', { timeout: 2500 })\n .json<{ data?: Partial<AppSettings> }>();\n return { apps: data?.apps ?? {} };\n },\n\n queries: {\n snippets: () =>\n queryOptions({\n queryKey: ['apps', 'snippets'],\n queryFn: () => apps.snippets(),\n // Snippets are static per session; one fetch per page load is enough.\n staleTime: Infinity,\n // No retry: this is awaited in rootBeforeLoad, so the router's default `retry: 1` would\n // make the SSR wait 2 x the 2500ms timeout (plus backoff) before failing open. The\n // 2500ms timeout must be the whole budget; the client fallback query does the retrying.\n retry: 0,\n }),\n\n settings: () =>\n queryOptions({\n queryKey: ['apps', 'settings'],\n queryFn: () => apps.settings(),\n // Encoded app ids and their buckets are stable per page; one fetch is enough.\n staleTime: Infinity,\n retry: 0,\n }),\n },\n};\n"]}
|
|
@@ -2,15 +2,15 @@ import { lazyComponent } from './chunk-VYGA5AT5.js';
|
|
|
2
2
|
|
|
3
3
|
// src/components/cart/lazy.ts
|
|
4
4
|
var LazyCartItem = lazyComponent(
|
|
5
|
-
() => import('./CartItem-
|
|
5
|
+
() => import('./CartItem-3KFTPQVF.js').then((m) => ({ default: m.CartItem }))
|
|
6
6
|
);
|
|
7
7
|
var LazyCartSummary = lazyComponent(
|
|
8
|
-
() => import('./CartSummary-
|
|
8
|
+
() => import('./CartSummary-I64SD4QX.js').then((m) => ({ default: m.CartSummary }))
|
|
9
9
|
);
|
|
10
10
|
var LazySeoCartWidget = lazyComponent(
|
|
11
|
-
() => import('./SeoCartWidget-
|
|
11
|
+
() => import('./SeoCartWidget-VL5TD2FU.js').then((m) => ({ default: m.SeoCartWidget }))
|
|
12
12
|
);
|
|
13
13
|
|
|
14
14
|
export { LazyCartItem, LazyCartSummary, LazySeoCartWidget };
|
|
15
|
-
//# sourceMappingURL=chunk-
|
|
16
|
-
//# sourceMappingURL=chunk-
|
|
15
|
+
//# sourceMappingURL=chunk-AZT4TALZ.js.map
|
|
16
|
+
//# sourceMappingURL=chunk-AZT4TALZ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/cart/lazy.ts"],"names":[],"mappings":";;;AAMO,IAAM,YAAA,GAAe,aAAA;AAAA,EAAc,MACxC,OAAO,wBAAY,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,QAAA,EAAS,CAAE;AAC5D;AAEO,IAAM,eAAA,GAAkB,aAAA;AAAA,EAAc,MAC3C,OAAO,2BAAe,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,WAAA,EAAY,CAAE;AAClE;AAEO,IAAM,iBAAA,GAAoB,aAAA;AAAA,EAAc,MAC7C,OAAO,6BAAiB,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,aAAA,EAAc,CAAE;AACtE","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/components/cart/lazy.ts"],"names":[],"mappings":";;;AAMO,IAAM,YAAA,GAAe,aAAA;AAAA,EAAc,MACxC,OAAO,wBAAY,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,QAAA,EAAS,CAAE;AAC5D;AAEO,IAAM,eAAA,GAAkB,aAAA;AAAA,EAAc,MAC3C,OAAO,2BAAe,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,WAAA,EAAY,CAAE;AAClE;AAEO,IAAM,iBAAA,GAAoB,aAAA;AAAA,EAAc,MAC7C,OAAO,6BAAiB,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,aAAA,EAAc,CAAE;AACtE","file":"chunk-AZT4TALZ.js","sourcesContent":["import { lazyComponent } from '../../utils/lazy-component';\n\n/**\n * Lazy-loaded cart components\n * Use these for code-splitting cart sections\n */\nexport const LazyCartItem = lazyComponent(() =>\n import('./CartItem').then((m) => ({ default: m.CartItem }))\n);\n\nexport const LazyCartSummary = lazyComponent(() =>\n import('./CartSummary').then((m) => ({ default: m.CartSummary }))\n);\n\nexport const LazySeoCartWidget = lazyComponent(() =>\n import('./SeoCartWidget').then((m) => ({ default: m.SeoCartWidget }))\n);\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { orThrow } from './chunk-
|
|
2
|
-
import { getActiveScope, api } from './chunk-
|
|
1
|
+
import { orThrow } from './chunk-SOLUKKTW.js';
|
|
2
|
+
import { getActiveScope, api } from './chunk-UXJAZ5JP.js';
|
|
3
3
|
import { queryOptions } from '@tanstack/react-query';
|
|
4
4
|
|
|
5
5
|
var category = {
|
|
@@ -26,5 +26,5 @@ var category = {
|
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
export { category };
|
|
29
|
-
//# sourceMappingURL=chunk-
|
|
30
|
-
//# sourceMappingURL=chunk-
|
|
29
|
+
//# sourceMappingURL=chunk-BPM6LSOV.js.map
|
|
30
|
+
//# sourceMappingURL=chunk-BPM6LSOV.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api/category.ts"],"names":[],"mappings":";;;;AAKO,IAAM,QAAA,GAAW;AAAA,EACtB,IAAA,EAAM,OAAO,EAAA,KAAkC;AAC7C,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CAAI,IAAI,CAAA,WAAA,EAAc,EAAE,CAAA,CAAE,CAAA,CAAE,IAAA,EAAyB;AAC5E,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AAAA,EAEA,aAAa,CAAC,EAAA,KAAkC,QAAQ,QAAA,CAAS,IAAA,CAAK,EAAE,CAAC,CAAA;AAAA,EAEzE,MAAM,YAAiC;AACrC,IAAA,MAAM,EAAE,MAAK,GAAI,MAAM,IAAI,GAAA,CAAI,YAAY,EAAE,IAAA,EAA2B;AACxE,IAAA,OAAO,QAAQ,EAAC;AAAA,EAClB,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,MAAA,EAAQ,CAAC,EAAA,KACP,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,YAAA,EAAc,QAAA,EAAU,EAAE,CAAA;AAAA,MACrC,OAAA,EAAS,MAAM,QAAA,CAAS,IAAA,CAAK,EAAE;AAAA,KAChC,CAAA;AAAA,IAEH,IAAA,EAAM,MACJ,YAAA,CAAa;AAAA;AAAA,MAEX,QAAA,EAAU,CAAC,YAAA,EAAc,MAAA,EAAQ,EAAE,KAAA,EAAO,cAAA,IAAkB,CAAA;AAAA,MAC5D,OAAA,EAAS,MAAM,QAAA,CAAS,IAAA;AAAK,KAC9B;AAAA;AAEP","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/api/category.ts"],"names":[],"mappings":";;;;AAKO,IAAM,QAAA,GAAW;AAAA,EACtB,IAAA,EAAM,OAAO,EAAA,KAAkC;AAC7C,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CAAI,IAAI,CAAA,WAAA,EAAc,EAAE,CAAA,CAAE,CAAA,CAAE,IAAA,EAAyB;AAC5E,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AAAA,EAEA,aAAa,CAAC,EAAA,KAAkC,QAAQ,QAAA,CAAS,IAAA,CAAK,EAAE,CAAC,CAAA;AAAA,EAEzE,MAAM,YAAiC;AACrC,IAAA,MAAM,EAAE,MAAK,GAAI,MAAM,IAAI,GAAA,CAAI,YAAY,EAAE,IAAA,EAA2B;AACxE,IAAA,OAAO,QAAQ,EAAC;AAAA,EAClB,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,MAAA,EAAQ,CAAC,EAAA,KACP,YAAA,CAAa;AAAA,MACX,QAAA,EAAU,CAAC,YAAA,EAAc,QAAA,EAAU,EAAE,CAAA;AAAA,MACrC,OAAA,EAAS,MAAM,QAAA,CAAS,IAAA,CAAK,EAAE;AAAA,KAChC,CAAA;AAAA,IAEH,IAAA,EAAM,MACJ,YAAA,CAAa;AAAA;AAAA,MAEX,QAAA,EAAU,CAAC,YAAA,EAAc,MAAA,EAAQ,EAAE,KAAA,EAAO,cAAA,IAAkB,CAAA;AAAA,MAC5D,OAAA,EAAS,MAAM,QAAA,CAAS,IAAA;AAAK,KAC9B;AAAA;AAEP","file":"chunk-BPM6LSOV.js","sourcesContent":["import { queryOptions } from '@tanstack/react-query';\nimport { api, getActiveScope } from './client';\nimport type { Category } from '../types';\nimport { orThrow } from '../providers/NavigationProvider';\n\nexport const category = {\n find: async (id: string): Promise<Category> => {\n const { data } = await api.get(`categories/${id}`).json<{ data: Category }>();\n return data;\n },\n\n findOrThrow: (id: string): Promise<Category> => orThrow(category.find(id)),\n\n list: async (): Promise<Category[]> => {\n const { data } = await api.get('categories').json<{ data: Category[] }>();\n return data ?? [];\n },\n\n queries: {\n detail: (id: string) =>\n queryOptions({\n queryKey: ['categories', 'detail', id],\n queryFn: () => category.find(id),\n }),\n\n list: () =>\n queryOptions({\n // Scope (branch) varies the API response — key must include it.\n queryKey: ['categories', 'list', { scope: getActiveScope() }],\n queryFn: () => category.list(),\n }),\n },\n};\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { api } from './chunk-
|
|
1
|
+
import { api } from './chunk-UXJAZ5JP.js';
|
|
2
2
|
|
|
3
3
|
// src/api/wallet.ts
|
|
4
4
|
var wallet = {
|
|
@@ -20,5 +20,5 @@ var wallet = {
|
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
export { wallet };
|
|
23
|
-
//# sourceMappingURL=chunk-
|
|
24
|
-
//# sourceMappingURL=chunk-
|
|
23
|
+
//# sourceMappingURL=chunk-CU2DV3Z4.js.map
|
|
24
|
+
//# sourceMappingURL=chunk-CU2DV3Z4.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api/wallet.ts"],"names":[],"mappings":";;;AAgCO,IAAM,MAAA,GAAS;AAAA,EACpB,IAAA,EAAM,OAAO,MAAA,GAA2B,EAAC,KAAiC;AACxE,IAAA,MAAM,EAAE,IAAA,GAAO,CAAA,EAAG,OAAA,GAAU,EAAA,EAAI,QAAO,GAAI,MAAA;AAE3C,IAAA,MAAM,YAAA,GAAe,IAAI,eAAA,EAAgB;AACzC,IAAA,YAAA,CAAa,GAAA,CAAI,MAAA,EAAQ,MAAA,CAAO,IAAI,CAAC,CAAA;AACrC,IAAA,YAAA,CAAa,GAAA,CAAI,UAAA,EAAY,MAAA,CAAO,OAAO,CAAC,CAAA;AAE5C,IAAA,MAAM,UAAmC,EAAC;AAC1C,IAAA,IAAI,MAAA,UAAgB,MAAA,GAAS,MAAA;AAE7B,IAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CACpB,GAAA,CAAI,CAAA,eAAA,EAAkB,YAAA,CAAa,QAAA,EAAU,CAAA,CAAA,EAAI,OAAc,CAAA,CAC/D,IAAA,EAAsE;AAEzE,IAAA,MAAM,YAAA,GAAe,SAAS,IAAA,CAAK,YAAA;AAEnC,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,YAAA,CAAa,IAAA,IAAQ,EAAC;AAAA,MAC7B,MAAM,YAAA,CAAa,aAAA;AAAA,MACnB,OAAA,EAAS,SAAS,IAAA,CAAK;AAAA,KACzB;AAAA,EACF;AACF","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/api/wallet.ts"],"names":[],"mappings":";;;AAgCO,IAAM,MAAA,GAAS;AAAA,EACpB,IAAA,EAAM,OAAO,MAAA,GAA2B,EAAC,KAAiC;AACxE,IAAA,MAAM,EAAE,IAAA,GAAO,CAAA,EAAG,OAAA,GAAU,EAAA,EAAI,QAAO,GAAI,MAAA;AAE3C,IAAA,MAAM,YAAA,GAAe,IAAI,eAAA,EAAgB;AACzC,IAAA,YAAA,CAAa,GAAA,CAAI,MAAA,EAAQ,MAAA,CAAO,IAAI,CAAC,CAAA;AACrC,IAAA,YAAA,CAAa,GAAA,CAAI,UAAA,EAAY,MAAA,CAAO,OAAO,CAAC,CAAA;AAE5C,IAAA,MAAM,UAAmC,EAAC;AAC1C,IAAA,IAAI,MAAA,UAAgB,MAAA,GAAS,MAAA;AAE7B,IAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CACpB,GAAA,CAAI,CAAA,eAAA,EAAkB,YAAA,CAAa,QAAA,EAAU,CAAA,CAAA,EAAI,OAAc,CAAA,CAC/D,IAAA,EAAsE;AAEzE,IAAA,MAAM,YAAA,GAAe,SAAS,IAAA,CAAK,YAAA;AAEnC,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,YAAA,CAAa,IAAA,IAAQ,EAAC;AAAA,MAC7B,MAAM,YAAA,CAAa,aAAA;AAAA,MACnB,OAAA,EAAS,SAAS,IAAA,CAAK;AAAA,KACzB;AAAA,EACF;AACF","file":"chunk-CU2DV3Z4.js","sourcesContent":["import { api } from './client';\n\nexport interface TransactionItem {\n id: number;\n order_id: number;\n transaction_type: string;\n action_type: string;\n type: string;\n title: string;\n description: string;\n amount: number;\n created_at: number;\n expired_at: number;\n}\n\nexport interface WalletListParams {\n page?: number;\n perPage?: number;\n signal?: AbortSignal;\n}\n\nexport interface WalletListResponse {\n data: TransactionItem[];\n next_page_url: string | null;\n}\n\nexport interface WalletListResult {\n items: TransactionItem[];\n next: string | null;\n balance: number;\n}\n\nexport const wallet = {\n list: async (params: WalletListParams = {}): Promise<WalletListResult> => {\n const { page = 1, perPage = 10, signal } = params;\n\n const searchParams = new URLSearchParams();\n searchParams.set('page', String(page));\n searchParams.set('per_page', String(perPage));\n\n const options: Record<string, unknown> = {};\n if (signal) options.signal = signal;\n\n const response = await api\n .get(`balance/wallet?${searchParams.toString()}`, options as any)\n .json<{ data: { transactions: WalletListResponse; balance: number } }>();\n\n const transactions = response.data.transactions;\n\n return {\n items: transactions.data ?? [],\n next: transactions.next_page_url,\n balance: response.data.balance,\n };\n },\n};\n"]}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { registry } from './chunk-Y32RHCOH.js';
|
|
2
|
+
import { useTranslation } from './chunk-TYNZ5B2B.js';
|
|
3
|
+
import { Image } from './chunk-TDIENKPW.js';
|
|
4
|
+
import { LazyImageModal } from './chunk-KYMWEUN2.js';
|
|
5
|
+
import { isNativeApp } from './chunk-3E3ABCPC.js';
|
|
6
|
+
import { useTwilight } from './chunk-DF6FBKDN.js';
|
|
7
|
+
import { lazyComponent } from './chunk-VYGA5AT5.js';
|
|
8
|
+
import { SallaSlider } from '@salla.sa/twilight-components-react/slider';
|
|
9
|
+
import { useMemo, useState, useEffect, Suspense } from 'react';
|
|
10
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
11
|
+
|
|
12
|
+
// src/components/product/lazy.ts
|
|
13
|
+
var LazyProductDetails = lazyComponent(
|
|
14
|
+
() => import('./ProductDetails-YYU7TJSU.js').then((m) => ({ default: m.ProductDetails }))
|
|
15
|
+
);
|
|
16
|
+
var LazyAddToCartForm = lazyComponent(
|
|
17
|
+
() => import('./AddToCartForm-EPTN5O3X.js').then((m) => ({ default: m.AddToCartForm }))
|
|
18
|
+
);
|
|
19
|
+
var PRODUCT_GALLERY_KEY = "product:gallery";
|
|
20
|
+
function legacyGalleryMedia(images) {
|
|
21
|
+
return images.flatMap((image) => {
|
|
22
|
+
if (image.three_d_image_url) return [{ url: image.three_d_image_url, type: "3d-image" }];
|
|
23
|
+
if (image.video_url) return [{ url: image.video_url, type: "video" }];
|
|
24
|
+
return image.url ? [{ url: image.url, type: "image" }] : [];
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function ProductGalleryContent({ product }) {
|
|
28
|
+
const { t } = useTranslation();
|
|
29
|
+
const { theme } = useTwilight();
|
|
30
|
+
const sliderId = `details-slider-${product.id}`;
|
|
31
|
+
const objectFit = theme.settings.slider_background_size ?? "cover";
|
|
32
|
+
const [preview, setPreview] = useState(null);
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
const raf = requestAnimationFrame(() => {
|
|
35
|
+
const el = document.getElementById(sliderId);
|
|
36
|
+
if (!el?.parentElement) return;
|
|
37
|
+
const { parentElement, nextSibling } = el;
|
|
38
|
+
parentElement.removeChild(el);
|
|
39
|
+
parentElement.insertBefore(el, nextSibling);
|
|
40
|
+
});
|
|
41
|
+
return () => cancelAnimationFrame(raf);
|
|
42
|
+
}, [sliderId]);
|
|
43
|
+
const images = product.images && product.images.length > 0 ? product.images : product.image?.url ? [product.image] : [];
|
|
44
|
+
const hasManyImages = images.length > 1;
|
|
45
|
+
const openNativeGallery = (selected) => {
|
|
46
|
+
if (!isNativeApp()) return false;
|
|
47
|
+
if (window.salla?.mobile?.openGallery?.(images, selected)) return true;
|
|
48
|
+
window.salla?.event.dispatch("mobile::gallery.open", { images: legacyGalleryMedia(images) });
|
|
49
|
+
return true;
|
|
50
|
+
};
|
|
51
|
+
return /* @__PURE__ */ jsxs("div", { className: "sidebar md:sticky top-24 w-full md:!w-2/4 rtl:ml-8 ltr:mr-8 pb-8 md:pb-16 overflow-hidden shrink-0", children: [
|
|
52
|
+
/* @__PURE__ */ jsxs(
|
|
53
|
+
SallaSlider,
|
|
54
|
+
{
|
|
55
|
+
id: sliderId,
|
|
56
|
+
className: "details-slider rounded-md image-slider",
|
|
57
|
+
type: "thumbs",
|
|
58
|
+
loop: false,
|
|
59
|
+
autoHeight: true,
|
|
60
|
+
listenToThumbnailsOption: true,
|
|
61
|
+
showThumbsControls: false,
|
|
62
|
+
sliderConfig: { watchOverflow: true, autoHeight: true },
|
|
63
|
+
children: [
|
|
64
|
+
product.promotion_title && /* @__PURE__ */ jsx("div", { className: "promotion-title", children: product.promotion_title }),
|
|
65
|
+
product.calories && /* @__PURE__ */ jsxs("div", { className: "absolute z-[2] top-4 rtl:left-4 ltr:right-4 bg-white shadow-sm flex flex-col justify-center items-center rounded-full w-20 h-20 md:w-24 md:h-24", children: [
|
|
66
|
+
/* @__PURE__ */ jsx("span", { className: "text-red-500 text-xl leading-none font-bold", children: product.calories }),
|
|
67
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-gray-500", children: t("pages.products.calories", "Calories") })
|
|
68
|
+
] }),
|
|
69
|
+
/* @__PURE__ */ jsx("div", { slot: "items", children: images.map((image, index) => /* @__PURE__ */ jsx(
|
|
70
|
+
ImageSlide,
|
|
71
|
+
{
|
|
72
|
+
image,
|
|
73
|
+
product,
|
|
74
|
+
index,
|
|
75
|
+
objectFit,
|
|
76
|
+
onPreview: setPreview,
|
|
77
|
+
onNativeOpen: openNativeGallery
|
|
78
|
+
},
|
|
79
|
+
image.id ?? image.three_d_image_url ?? image.video_url ?? image.url
|
|
80
|
+
)) }),
|
|
81
|
+
hasManyImages && /* @__PURE__ */ jsx("div", { slot: "thumbs", children: images.map((image, index) => /* @__PURE__ */ jsx(
|
|
82
|
+
ThumbSlide,
|
|
83
|
+
{
|
|
84
|
+
image,
|
|
85
|
+
index
|
|
86
|
+
},
|
|
87
|
+
image.id ?? image.three_d_image_url ?? image.video_url ?? image.url
|
|
88
|
+
)) })
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
),
|
|
92
|
+
/* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(
|
|
93
|
+
LazyImageModal,
|
|
94
|
+
{
|
|
95
|
+
isOpen: !!preview,
|
|
96
|
+
onClose: () => setPreview(null),
|
|
97
|
+
src: preview?.src ?? "",
|
|
98
|
+
alt: preview?.alt
|
|
99
|
+
}
|
|
100
|
+
) })
|
|
101
|
+
] });
|
|
102
|
+
}
|
|
103
|
+
function ProductGallery(props) {
|
|
104
|
+
const Component = useMemo(() => {
|
|
105
|
+
const resolved = registry.resolve(PRODUCT_GALLERY_KEY);
|
|
106
|
+
return resolved === ProductGallery ? null : resolved;
|
|
107
|
+
}, []);
|
|
108
|
+
if (Component) {
|
|
109
|
+
return /* @__PURE__ */ jsx(Component, { ...props });
|
|
110
|
+
}
|
|
111
|
+
return /* @__PURE__ */ jsx(ProductGalleryContent, { ...props });
|
|
112
|
+
}
|
|
113
|
+
function ImageSlide({
|
|
114
|
+
image,
|
|
115
|
+
product,
|
|
116
|
+
index,
|
|
117
|
+
objectFit,
|
|
118
|
+
onPreview,
|
|
119
|
+
onNativeOpen
|
|
120
|
+
}) {
|
|
121
|
+
const [loaded, setLoaded] = useState(false);
|
|
122
|
+
const isVideo = Boolean(image.video_url);
|
|
123
|
+
if (image.three_d_image_url) {
|
|
124
|
+
return (
|
|
125
|
+
// biome-ignore lint/a11y/noStaticElementInteractions: model-viewer is an interactive web component.
|
|
126
|
+
/* @__PURE__ */ jsx(
|
|
127
|
+
"model-viewer",
|
|
128
|
+
{
|
|
129
|
+
style: { minHeight: "500px" },
|
|
130
|
+
className: "swiper-slide model-entry w-full h-full",
|
|
131
|
+
loading: "lazy",
|
|
132
|
+
"camera-controls": true,
|
|
133
|
+
"touch-action": "pan-y",
|
|
134
|
+
"auto-rotate": true,
|
|
135
|
+
poster: image.url || void 0,
|
|
136
|
+
src: image.three_d_image_url,
|
|
137
|
+
"shadow-intensity": "1",
|
|
138
|
+
alt: image.alt,
|
|
139
|
+
onClick: () => onNativeOpen(image)
|
|
140
|
+
}
|
|
141
|
+
)
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
return /* @__PURE__ */ jsx(
|
|
145
|
+
"a",
|
|
146
|
+
{
|
|
147
|
+
"data-fslightbox": `product_${product.id}`,
|
|
148
|
+
"data-img-id": image.id,
|
|
149
|
+
"data-slid-index": index,
|
|
150
|
+
...image.video_url ? { "data-video-src": image.video_url } : {},
|
|
151
|
+
"data-caption": image.alt,
|
|
152
|
+
"data-infinite": "false",
|
|
153
|
+
"data-type": image.video_url ? "youtube" : "image",
|
|
154
|
+
href: image.video_url || image.url,
|
|
155
|
+
...isVideo ? { target: "_blank", rel: "noopener noreferrer" } : {},
|
|
156
|
+
onClick: (event) => {
|
|
157
|
+
if (onNativeOpen(image)) {
|
|
158
|
+
event.preventDefault();
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
if (isVideo || !image.url) return;
|
|
162
|
+
event.preventDefault();
|
|
163
|
+
onPreview({ src: image.url, alt: image.alt || product.name });
|
|
164
|
+
},
|
|
165
|
+
"aria-label": product.name,
|
|
166
|
+
className: `swiper-slide magnify-wrapper homeslider__slide ${image.video_url ? "video-entry" : ""}`,
|
|
167
|
+
children: /* @__PURE__ */ jsx("div", { className: `w-full ${loaded ? "" : "aspect-square bg-gray-100 animate-pulse"}`, children: /* @__PURE__ */ jsx(
|
|
168
|
+
Image,
|
|
169
|
+
{
|
|
170
|
+
id: String(image.id),
|
|
171
|
+
src: image.url,
|
|
172
|
+
alt: image.alt || product.name,
|
|
173
|
+
className: `h-full w-full object-${objectFit}`,
|
|
174
|
+
aspectRatio: "1/1",
|
|
175
|
+
priority: index === 0,
|
|
176
|
+
noWrapper: true,
|
|
177
|
+
onLoad: () => setLoaded(true)
|
|
178
|
+
}
|
|
179
|
+
) })
|
|
180
|
+
}
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
function ThumbSlide({ image, index }) {
|
|
184
|
+
return /* @__PURE__ */ jsx(
|
|
185
|
+
"div",
|
|
186
|
+
{
|
|
187
|
+
className: `slide--one-fourth ${image.video_url ? "video-entry" : ""} ${image.three_d_image_url ? "model-entry" : ""}`,
|
|
188
|
+
"data-caption": image.alt,
|
|
189
|
+
children: /* @__PURE__ */ jsx(
|
|
190
|
+
Image,
|
|
191
|
+
{
|
|
192
|
+
src: image.url,
|
|
193
|
+
alt: image.alt || "",
|
|
194
|
+
className: "object-cover w-full h-full bg-gray-100 rounded-md overflow-hidden",
|
|
195
|
+
title: image.alt,
|
|
196
|
+
priority: index < 5,
|
|
197
|
+
noWrapper: true
|
|
198
|
+
}
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export { LazyAddToCartForm, LazyProductDetails, ProductGallery };
|
|
205
|
+
//# sourceMappingURL=chunk-F3SXHQU4.js.map
|
|
206
|
+
//# sourceMappingURL=chunk-F3SXHQU4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/product/lazy.ts","../src/components/product/ProductGallery.tsx"],"names":[],"mappings":"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","file":"chunk-F3SXHQU4.js","sourcesContent":["import { lazyComponent } from '../../utils/lazy-component';\n\nexport const LazyProductDetails = lazyComponent(() =>\n import('./ProductDetails').then((m) => ({ default: m.ProductDetails }))\n);\n\nexport const LazyAddToCartForm = lazyComponent(() =>\n import('./AddToCartForm').then((m) => ({ default: m.AddToCartForm }))\n);\n","import { SallaSlider } from '@salla.sa/twilight-components-react/slider';\nimport { Suspense, useEffect, useMemo, useState } from 'react';\nimport { registry } from '../ComponentRegistry';\nimport { useTwilight } from '../../providers/TwilightProvider';\nimport { useTranslation } from '../../providers/I18nProvider';\nimport type { Product, ProductImage } from '../../types';\nimport { Image } from '../common/Image';\nimport { ImageModal } from '../modal';\nimport { isNativeApp } from '../../native-app';\n\nconst PRODUCT_GALLERY_KEY = 'product:gallery';\n\nexport interface ProductGalleryProps {\n product: Product;\n}\n\ntype ImagePreview = { src: string; alt: string };\ntype GalleryMedia = { url: string; type: 'image' | 'video' | '3d-image' };\n\n/**\n * The engine's own `mobile::gallery.open` payload from before `salla.mobile.openGallery`: a video's\n * link and a 3D model's file go in `url`, with no ids. Sent when the SDK has no `openGallery`\n * (Twilight before 2.14.569) or declines inside the app, so those stores keep the gallery they had.\n */\nfunction legacyGalleryMedia(images: ProductImage[]): GalleryMedia[] {\n return images.flatMap<GalleryMedia>((image) => {\n if (image.three_d_image_url) return [{ url: image.three_d_image_url, type: '3d-image' }];\n if (image.video_url) return [{ url: image.video_url, type: 'video' }];\n return image.url ? [{ url: image.url, type: 'image' }] : [];\n });\n}\n\nfunction ProductGalleryContent({ product }: ProductGalleryProps) {\n const { t } = useTranslation();\n const { theme } = useTwilight();\n const sliderId = `details-slider-${product.id}`;\n const objectFit = theme.settings.slider_background_size ?? 'cover';\n\n // Clicking an image opens an in-app lightbox instead of navigating to the CDN URL.\n const [preview, setPreview] = useState<ImagePreview | null>(null);\n\n useEffect(() => {\n const raf = requestAnimationFrame(() => {\n const el = document.getElementById(sliderId);\n if (!el?.parentElement) return;\n const { parentElement, nextSibling } = el;\n parentElement.removeChild(el);\n parentElement.insertBefore(el, nextSibling);\n });\n return () => cancelAnimationFrame(raf);\n }, [sliderId]);\n\n // The product-details API only returns `image` (singular).\n // Fall back so the main image always renders even without the full gallery array.\n const images: ProductImage[] =\n product.images && product.images.length > 0\n ? product.images\n : product.image?.url\n ? [product.image]\n : [];\n\n const hasManyImages = images.length > 1;\n const openNativeGallery = (selected: ProductImage) => {\n if (!isNativeApp()) return false;\n if (window.salla?.mobile?.openGallery?.(images, selected)) return true;\n window.salla?.event.dispatch('mobile::gallery.open', { images: legacyGalleryMedia(images) });\n return true;\n };\n\n return (\n <div className=\"sidebar md:sticky top-24 w-full md:!w-2/4 rtl:ml-8 ltr:mr-8 pb-8 md:pb-16 overflow-hidden shrink-0\">\n <SallaSlider\n id={sliderId}\n className=\"details-slider rounded-md image-slider\"\n type=\"thumbs\"\n loop={false}\n autoHeight\n listenToThumbnailsOption\n showThumbsControls={false}\n sliderConfig={{ watchOverflow: true, autoHeight: true }}\n >\n {product.promotion_title && (\n <div className=\"promotion-title\">{product.promotion_title}</div>\n )}\n\n {product.calories && (\n <div className=\"absolute z-[2] top-4 rtl:left-4 ltr:right-4 bg-white shadow-sm flex flex-col justify-center items-center rounded-full w-20 h-20 md:w-24 md:h-24\">\n <span className=\"text-red-500 text-xl leading-none font-bold\">{product.calories}</span>\n <span className=\"text-xs text-gray-500\">\n {t('pages.products.calories', 'Calories')}\n </span>\n </div>\n )}\n\n <div slot=\"items\">\n {images.map((image, index) => (\n <ImageSlide\n key={image.id ?? image.three_d_image_url ?? image.video_url ?? image.url}\n image={image}\n product={product}\n index={index}\n objectFit={objectFit}\n onPreview={setPreview}\n onNativeOpen={openNativeGallery}\n />\n ))}\n </div>\n\n {hasManyImages && (\n <div slot=\"thumbs\">\n {images.map((image, index) => (\n <ThumbSlide\n key={image.id ?? image.three_d_image_url ?? image.video_url ?? image.url}\n image={image}\n index={index}\n />\n ))}\n </div>\n )}\n </SallaSlider>\n\n <Suspense fallback={null}>\n <ImageModal\n isOpen={!!preview}\n onClose={() => setPreview(null)}\n src={preview?.src ?? ''}\n alt={preview?.alt}\n />\n </Suspense>\n </div>\n );\n}\n\nexport function ProductGallery(props: ProductGalleryProps) {\n const Component = useMemo(() => {\n const resolved = registry.resolve<ProductGalleryProps>(PRODUCT_GALLERY_KEY);\n // A theme that seeds the key with this component (register + override) would\n // otherwise recurse into itself when it has not actually overridden anything.\n return resolved === ProductGallery ? null : resolved;\n }, []);\n\n if (Component) {\n return <Component {...props} />;\n }\n\n return <ProductGalleryContent {...props} />;\n}\n\nfunction ImageSlide({\n image,\n product,\n index,\n objectFit,\n onPreview,\n onNativeOpen,\n}: {\n image: ProductImage;\n product: Product;\n index: number;\n objectFit: 'cover' | 'contain';\n onPreview: (preview: ImagePreview) => void;\n onNativeOpen: (image: ProductImage) => boolean;\n}) {\n const [loaded, setLoaded] = useState(false);\n const isVideo = Boolean(image.video_url);\n\n if (image.three_d_image_url) {\n return (\n // biome-ignore lint/a11y/noStaticElementInteractions: model-viewer is an interactive web component.\n <model-viewer\n style={{ minHeight: '500px' }}\n className=\"swiper-slide model-entry w-full h-full\"\n loading=\"lazy\"\n camera-controls\n touch-action=\"pan-y\"\n auto-rotate\n poster={image.url || undefined}\n src={image.three_d_image_url}\n shadow-intensity=\"1\"\n alt={image.alt}\n onClick={() => onNativeOpen(image)}\n ></model-viewer>\n );\n }\n\n return (\n <a\n data-fslightbox={`product_${product.id}`}\n data-img-id={image.id}\n data-slid-index={index}\n {...(image.video_url ? { 'data-video-src': image.video_url } : {})}\n data-caption={image.alt}\n data-infinite=\"false\"\n data-type={image.video_url ? 'youtube' : 'image'}\n href={image.video_url || image.url}\n // FsLightbox isn't loaded in this React theme, so the bare href would leave the SPA.\n // Open images in an in-app lightbox; let videos open in a new tab.\n {...(isVideo ? { target: '_blank', rel: 'noopener noreferrer' } : {})}\n onClick={(event) => {\n if (onNativeOpen(image)) {\n event.preventDefault();\n return;\n }\n if (isVideo || !image.url) return;\n event.preventDefault();\n onPreview({ src: image.url, alt: image.alt || product.name });\n }}\n aria-label={product.name}\n className={`swiper-slide magnify-wrapper homeslider__slide ${image.video_url ? 'video-entry' : ''}`}\n >\n <div className={`w-full ${loaded ? '' : 'aspect-square bg-gray-100 animate-pulse'}`}>\n <Image\n id={String(image.id)}\n src={image.url}\n alt={image.alt || product.name}\n className={`h-full w-full object-${objectFit}`}\n aspectRatio=\"1/1\"\n priority={index === 0}\n noWrapper\n onLoad={() => setLoaded(true)}\n />\n </div>\n </a>\n );\n}\n\nfunction ThumbSlide({ image, index }: { image: ProductImage; index: number }) {\n return (\n <div\n className={`slide--one-fourth ${image.video_url ? 'video-entry' : ''} ${image.three_d_image_url ? 'model-entry' : ''}`}\n data-caption={image.alt}\n >\n <Image\n src={image.url}\n alt={image.alt || ''}\n className=\"object-cover w-full h-full bg-gray-100 rounded-md overflow-hidden\"\n title={image.alt}\n priority={index < 5}\n noWrapper\n />\n </div>\n );\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { api } from './chunk-
|
|
1
|
+
import { api } from './chunk-UXJAZ5JP.js';
|
|
2
2
|
import { queryOptions } from '@tanstack/react-query';
|
|
3
3
|
|
|
4
4
|
var notification = {
|
|
@@ -24,5 +24,5 @@ var notification = {
|
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
export { notification };
|
|
27
|
-
//# sourceMappingURL=chunk-
|
|
28
|
-
//# sourceMappingURL=chunk-
|
|
27
|
+
//# sourceMappingURL=chunk-GIYRCRS6.js.map
|
|
28
|
+
//# sourceMappingURL=chunk-GIYRCRS6.js.map
|