@salla.sa/twilight-theme-engine 1.0.102 → 1.0.104

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.
Files changed (184) hide show
  1. package/dist/{AddToCartForm-PGX4TKK5.js → AddToCartForm-ZJT6JJHQ.js} +3 -3
  2. package/dist/{AddToCartForm-PGX4TKK5.js.map → AddToCartForm-ZJT6JJHQ.js.map} +1 -1
  3. package/dist/{BlogAuthorPage-SLTGPBTO.js → BlogAuthorPage-KCV5TAWN.js} +11 -11
  4. package/dist/{BlogAuthorPage-SLTGPBTO.js.map → BlogAuthorPage-KCV5TAWN.js.map} +1 -1
  5. package/dist/{BlogCategoryPage-BSNM6O7D.js → BlogCategoryPage-DNDZ76UW.js} +11 -11
  6. package/dist/{BlogCategoryPage-BSNM6O7D.js.map → BlogCategoryPage-DNDZ76UW.js.map} +1 -1
  7. package/dist/{BlogPage-SFMPPVK6.js → BlogPage-STXNCRQP.js} +9 -9
  8. package/dist/{BlogPage-SFMPPVK6.js.map → BlogPage-STXNCRQP.js.map} +1 -1
  9. package/dist/{BlogSinglePage-HXPZJMOO.js → BlogSinglePage-JJWYKJHP.js} +9 -9
  10. package/dist/{BlogSinglePage-HXPZJMOO.js.map → BlogSinglePage-JJWYKJHP.js.map} +1 -1
  11. package/dist/{BlogTagPage-O23AU64T.js → BlogTagPage-ZE2XOPK4.js} +11 -11
  12. package/dist/{BlogTagPage-O23AU64T.js.map → BlogTagPage-ZE2XOPK4.js.map} +1 -1
  13. package/dist/{BrandsPage-NNEO7WBD.js → BrandsPage-BDJ3JRDD.js} +10 -10
  14. package/dist/{BrandsPage-NNEO7WBD.js.map → BrandsPage-BDJ3JRDD.js.map} +1 -1
  15. package/dist/{Breadcrumb-ZOGOEHIT.js → Breadcrumb-OK37EG4K.js} +9 -9
  16. package/dist/{Breadcrumb-ZOGOEHIT.js.map → Breadcrumb-OK37EG4K.js.map} +1 -1
  17. package/dist/{CartItem-AIVN7POE.js → CartItem-N4B3L2QT.js} +9 -9
  18. package/dist/{CartItem-AIVN7POE.js.map → CartItem-N4B3L2QT.js.map} +1 -1
  19. package/dist/{CartSummary-II45KD76.js → CartSummary-27VDB6CC.js} +9 -9
  20. package/dist/{CartSummary-II45KD76.js.map → CartSummary-27VDB6CC.js.map} +1 -1
  21. package/dist/{Copyright-CCX4G6HS.js → Copyright-UOOJCPCK.js} +3 -3
  22. package/dist/{Copyright-CCX4G6HS.js.map → Copyright-UOOJCPCK.js.map} +1 -1
  23. package/dist/{CustomerLayout-U4MXMKJE.js → CustomerLayout-2TU63GI2.js} +9 -9
  24. package/dist/{CustomerLayout-U4MXMKJE.js.map → CustomerLayout-2TU63GI2.js.map} +1 -1
  25. package/dist/{Footer-INYXRJQ4.js → Footer-QJHB3FO7.js} +4 -4
  26. package/dist/{Footer-INYXRJQ4.js.map → Footer-QJHB3FO7.js.map} +1 -1
  27. package/dist/{Header-ICAHI5OA.js → Header-2GMIMJ2A.js} +5 -5
  28. package/dist/{Header-ICAHI5OA.js.map → Header-2GMIMJ2A.js.map} +1 -1
  29. package/dist/{LoyaltyPage-PBT32LV7.js → LoyaltyPage-H2FY4IBM.js} +9 -9
  30. package/dist/{LoyaltyPage-PBT32LV7.js.map → LoyaltyPage-H2FY4IBM.js.map} +1 -1
  31. package/dist/{LoyaltyPointsPage-6LJF7ZFO.js → LoyaltyPointsPage-FVXJNJKL.js} +3 -3
  32. package/dist/{LoyaltyPointsPage-6LJF7ZFO.js.map → LoyaltyPointsPage-FVXJNJKL.js.map} +1 -1
  33. package/dist/{MainMenu-6AQECV5E.js → MainMenu-COKDB5AQ.js} +3 -3
  34. package/dist/{MainMenu-6AQECV5E.js.map → MainMenu-COKDB5AQ.js.map} +1 -1
  35. package/dist/{MasterLayout-RPVSZOED.js → MasterLayout-4N7LOXPC.js} +9 -9
  36. package/dist/{MasterLayout-RPVSZOED.js.map → MasterLayout-4N7LOXPC.js.map} +1 -1
  37. package/dist/{MobileMenu-JGCNAGQN.js → MobileMenu-ELEUZZKM.js} +9 -9
  38. package/dist/{MobileMenu-JGCNAGQN.js.map → MobileMenu-ELEUZZKM.js.map} +1 -1
  39. package/dist/{NotificationsPage-RTIXES2K.js → NotificationsPage-DWUGY2XG.js} +9 -9
  40. package/dist/{NotificationsPage-RTIXES2K.js.map → NotificationsPage-DWUGY2XG.js.map} +1 -1
  41. package/dist/{OrderSinglePage-TAVOOUEP.js → OrderSinglePage-WR3L5PLV.js} +10 -10
  42. package/dist/{OrderSinglePage-TAVOOUEP.js.map → OrderSinglePage-WR3L5PLV.js.map} +1 -1
  43. package/dist/{OrdersPage-AYYJBHOJ.js → OrdersPage-XQ2D5ES5.js} +9 -9
  44. package/dist/{OrdersPage-AYYJBHOJ.js.map → OrdersPage-XQ2D5ES5.js.map} +1 -1
  45. package/dist/{PageSingle-4ASICFTJ.js → PageSingle-VU46ZY7F.js} +3 -3
  46. package/dist/{PageSingle-4ASICFTJ.js.map → PageSingle-VU46ZY7F.js.map} +1 -1
  47. package/dist/{ProductDetails-ZNBMM557.js → ProductDetails-YYWUUS26.js} +3 -3
  48. package/dist/{ProductDetails-ZNBMM557.js.map → ProductDetails-YYWUUS26.js.map} +1 -1
  49. package/dist/{ProfilePage-BBXMTKL2.js → ProfilePage-LHB2RELA.js} +9 -9
  50. package/dist/{ProfilePage-BBXMTKL2.js.map → ProfilePage-LHB2RELA.js.map} +1 -1
  51. package/dist/{ReviewsPage-4BSQEFPW.js → ReviewsPage-5TSLYA2V.js} +3 -3
  52. package/dist/{ReviewsPage-4BSQEFPW.js.map → ReviewsPage-5TSLYA2V.js.map} +1 -1
  53. package/dist/{SeoCartWidget-THR2WPLF.js → SeoCartWidget-DATW77M6.js} +9 -9
  54. package/dist/{SeoCartWidget-THR2WPLF.js.map → SeoCartWidget-DATW77M6.js.map} +1 -1
  55. package/dist/{SettingsPage-MUJ4767L.js → SettingsPage-MDQWPGD7.js} +9 -9
  56. package/dist/{SettingsPage-MUJ4767L.js.map → SettingsPage-MDQWPGD7.js.map} +1 -1
  57. package/dist/{StoreClosedNotification-3SVCHYWS.js → StoreClosedNotification-FJS7YUCR.js} +10 -10
  58. package/dist/{StoreClosedNotification-3SVCHYWS.js.map → StoreClosedNotification-FJS7YUCR.js.map} +1 -1
  59. package/dist/{TestimonialsPage-JKNNN7PT.js → TestimonialsPage-2RNRU4QT.js} +3 -3
  60. package/dist/{TestimonialsPage-JKNNN7PT.js.map → TestimonialsPage-2RNRU4QT.js.map} +1 -1
  61. package/dist/{ThankYouPage-6NLWMBY4.js → ThankYouPage-OZKNDH4H.js} +9 -9
  62. package/dist/{ThankYouPage-6NLWMBY4.js.map → ThankYouPage-OZKNDH4H.js.map} +1 -1
  63. package/dist/{WalletPage-B6OEJKBR.js → WalletPage-BSEA7PKK.js} +9 -9
  64. package/dist/{WalletPage-B6OEJKBR.js.map → WalletPage-BSEA7PKK.js.map} +1 -1
  65. package/dist/{WishlistPage-7BYBM24I.js → WishlistPage-QEB7EFDE.js} +11 -11
  66. package/dist/{WishlistPage-7BYBM24I.js.map → WishlistPage-QEB7EFDE.js.map} +1 -1
  67. package/dist/api/blog.js +2 -2
  68. package/dist/api/brands.js +2 -2
  69. package/dist/api/cart.js +2 -2
  70. package/dist/api/category.js +2 -2
  71. package/dist/api/loyalty.js +2 -2
  72. package/dist/api/order.js +2 -2
  73. package/dist/api/page.js +2 -2
  74. package/dist/api/product.js +2 -2
  75. package/dist/api/wishlist.js +3 -3
  76. package/dist/{chunk-ICYJD26Y.js → chunk-2JQUBER5.js} +6 -6
  77. package/dist/{chunk-ICYJD26Y.js.map → chunk-2JQUBER5.js.map} +1 -1
  78. package/dist/{chunk-7OB2DG2K.js → chunk-556Q5ATS.js} +3 -3
  79. package/dist/{chunk-7OB2DG2K.js.map → chunk-556Q5ATS.js.map} +1 -1
  80. package/dist/{chunk-NFLDOZOM.js → chunk-5A6QUNZ5.js} +4 -4
  81. package/dist/{chunk-NFLDOZOM.js.map → chunk-5A6QUNZ5.js.map} +1 -1
  82. package/dist/{chunk-IOUOF5KK.js → chunk-5ISYMZ62.js} +3 -3
  83. package/dist/{chunk-IOUOF5KK.js.map → chunk-5ISYMZ62.js.map} +1 -1
  84. package/dist/{chunk-QTH6GGUH.js → chunk-A75QNVGV.js} +3 -3
  85. package/dist/{chunk-QTH6GGUH.js.map → chunk-A75QNVGV.js.map} +1 -1
  86. package/dist/{chunk-B3EOUBP3.js → chunk-AVYPAASH.js} +7 -7
  87. package/dist/{chunk-B3EOUBP3.js.map → chunk-AVYPAASH.js.map} +1 -1
  88. package/dist/{chunk-LMJUQ6FW.js → chunk-BCADAQXY.js} +3 -3
  89. package/dist/{chunk-LMJUQ6FW.js.map → chunk-BCADAQXY.js.map} +1 -1
  90. package/dist/{chunk-ZE4EZOXQ.js → chunk-E2GBYIGH.js} +4 -4
  91. package/dist/{chunk-ZE4EZOXQ.js.map → chunk-E2GBYIGH.js.map} +1 -1
  92. package/dist/{chunk-6LRTCW27.js → chunk-EM46TNHW.js} +3 -3
  93. package/dist/{chunk-6LRTCW27.js.map → chunk-EM46TNHW.js.map} +1 -1
  94. package/dist/{chunk-UWW4I3L3.js → chunk-FNZ4MEUH.js} +4 -4
  95. package/dist/{chunk-UWW4I3L3.js.map → chunk-FNZ4MEUH.js.map} +1 -1
  96. package/dist/{chunk-Y6J6NYNK.js → chunk-GWW2YPJ3.js} +3 -3
  97. package/dist/{chunk-Y6J6NYNK.js.map → chunk-GWW2YPJ3.js.map} +1 -1
  98. package/dist/{chunk-RJTIP2L3.js → chunk-I3DKJNUZ.js} +3 -3
  99. package/dist/{chunk-RJTIP2L3.js.map → chunk-I3DKJNUZ.js.map} +1 -1
  100. package/dist/{chunk-W5CR5IJW.js → chunk-IATZL5LC.js} +5 -5
  101. package/dist/{chunk-W5CR5IJW.js.map → chunk-IATZL5LC.js.map} +1 -1
  102. package/dist/{chunk-PCRXL4RU.js → chunk-J6T5YOUW.js} +3 -3
  103. package/dist/{chunk-PCRXL4RU.js.map → chunk-J6T5YOUW.js.map} +1 -1
  104. package/dist/{chunk-GT2L5IJ4.js → chunk-K4ON2CI7.js} +3 -2
  105. package/dist/chunk-K4ON2CI7.js.map +1 -0
  106. package/dist/{chunk-OK6AE7EJ.js → chunk-NTK25X6V.js} +6 -6
  107. package/dist/{chunk-OK6AE7EJ.js.map → chunk-NTK25X6V.js.map} +1 -1
  108. package/dist/{chunk-RXZ5ZZ3I.js → chunk-OSTGSFJW.js} +5 -5
  109. package/dist/{chunk-RXZ5ZZ3I.js.map → chunk-OSTGSFJW.js.map} +1 -1
  110. package/dist/{chunk-224CL4SD.js → chunk-OXA277JH.js} +3 -3
  111. package/dist/{chunk-224CL4SD.js.map → chunk-OXA277JH.js.map} +1 -1
  112. package/dist/{chunk-N45X7D55.js → chunk-OXMUPNMH.js} +2 -2
  113. package/dist/chunk-OXMUPNMH.js.map +1 -0
  114. package/dist/chunk-PJVQMZHM.js +14 -0
  115. package/dist/{chunk-JJSQWN5M.js.map → chunk-PJVQMZHM.js.map} +1 -1
  116. package/dist/{chunk-IGD4G3SP.js → chunk-PLGCIXHX.js} +3 -3
  117. package/dist/{chunk-IGD4G3SP.js.map → chunk-PLGCIXHX.js.map} +1 -1
  118. package/dist/{chunk-VYWEI635.js → chunk-QQRU2L23.js} +6 -6
  119. package/dist/{chunk-VYWEI635.js.map → chunk-QQRU2L23.js.map} +1 -1
  120. package/dist/{chunk-RI5PSI34.js → chunk-W23NEGCL.js} +3 -3
  121. package/dist/{chunk-RI5PSI34.js.map → chunk-W23NEGCL.js.map} +1 -1
  122. package/dist/{chunk-TSAIM4XM.js → chunk-WCCZYPYM.js} +3 -3
  123. package/dist/{chunk-TSAIM4XM.js.map → chunk-WCCZYPYM.js.map} +1 -1
  124. package/dist/{chunk-6EBOQCET.js → chunk-XLCLZIWF.js} +4 -4
  125. package/dist/{chunk-6EBOQCET.js.map → chunk-XLCLZIWF.js.map} +1 -1
  126. package/dist/{chunk-VVZLYCKO.js → chunk-YBEZB5WO.js} +11 -11
  127. package/dist/{chunk-VVZLYCKO.js.map → chunk-YBEZB5WO.js.map} +1 -1
  128. package/dist/{chunk-FV6PNN6N.js → chunk-ZP7H4W2B.js} +3 -3
  129. package/dist/{chunk-FV6PNN6N.js.map → chunk-ZP7H4W2B.js.map} +1 -1
  130. package/dist/components/cart/index.js +1 -1
  131. package/dist/components/common/index.js +1 -1
  132. package/dist/components/drawer/index.js +7 -7
  133. package/dist/components/home/index.js +10 -10
  134. package/dist/components/layout/index.js +1 -1
  135. package/dist/components/product/index.js +8 -8
  136. package/dist/components/store/index.js +9 -9
  137. package/dist/dev/editor/index.js +2 -2
  138. package/dist/dev/editor/index.js.map +1 -1
  139. package/dist/dev/editor/pickers.d.ts +1 -1
  140. package/dist/dev/editor/pickers.d.ts.map +1 -1
  141. package/dist/dev/index.js +2 -2
  142. package/dist/dev/schema-types.d.ts +1 -1
  143. package/dist/dev/schema-types.d.ts.map +1 -1
  144. package/dist/{document-class-YIOOJTJG.js → document-class-OWGWP7TU.js} +5 -5
  145. package/dist/{document-class-YIOOJTJG.js.map → document-class-OWGWP7TU.js.map} +1 -1
  146. package/dist/hooks/index.js +7 -7
  147. package/dist/hooks/useGtm.js +7 -7
  148. package/dist/hooks/useMoney.js +7 -7
  149. package/dist/hooks/useStore.js +7 -7
  150. package/dist/index.js +7 -7
  151. package/dist/{navigation-GQA6OA42.js → navigation-4ASVNTMT.js} +3 -3
  152. package/dist/{navigation-GQA6OA42.js.map → navigation-4ASVNTMT.js.map} +1 -1
  153. package/dist/{navigation-RO3T4FDQ.js → navigation-BTWSY7VI.js} +4 -4
  154. package/dist/{navigation-RO3T4FDQ.js.map → navigation-BTWSY7VI.js.map} +1 -1
  155. package/dist/{not-found-3XVHUWBP.js → not-found-EFNMP37O.js} +10 -10
  156. package/dist/{not-found-3XVHUWBP.js.map → not-found-EFNMP37O.js.map} +1 -1
  157. package/dist/providers/NavigationProvider.d.ts +4 -1
  158. package/dist/providers/NavigationProvider.d.ts.map +1 -1
  159. package/dist/providers/index.js +7 -7
  160. package/dist/routes/account/orders.js +3 -3
  161. package/dist/routes/account.js +10 -10
  162. package/dist/routes/blog.js +7 -7
  163. package/dist/routes/brands.js +3 -3
  164. package/dist/routes/cart.js +14 -14
  165. package/dist/routes/home.js +11 -11
  166. package/dist/routes/index.js +2 -2
  167. package/dist/routes/loyalty.js +4 -4
  168. package/dist/routes/page.js +3 -3
  169. package/dist/routes/product-listing.js +12 -12
  170. package/dist/routes/product.js +10 -10
  171. package/dist/routes/seo-redirects.js +2 -2
  172. package/dist/routes/testimonials.js +2 -2
  173. package/dist/routes/thank-you.js +3 -3
  174. package/dist/skeleton.js +11 -11
  175. package/dist/{store-lookup-OZTXCMWE.js → store-lookup-4ZBTHRZA.js} +8 -8
  176. package/dist/{store-lookup-OZTXCMWE.js.map → store-lookup-4ZBTHRZA.js.map} +1 -1
  177. package/dist/tanstack.js +5 -5
  178. package/dist/vite/index.js +8 -2
  179. package/dist/vite/index.js.map +1 -1
  180. package/dist/vite/plugins/twilight-schema.d.ts.map +1 -1
  181. package/package.json +1 -1
  182. package/dist/chunk-GT2L5IJ4.js.map +0 -1
  183. package/dist/chunk-JJSQWN5M.js +0 -14
  184. package/dist/chunk-N45X7D55.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"twilight-schema.d.ts","sourceRoot":"","sources":["../../../src/vite/plugins/twilight-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAEV,SAAS,EAIV,MAAM,wBAAwB,CAAC;AAyThC,2EAA2E;AAC3E,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,SAAS,CAkD3D"}
1
+ {"version":3,"file":"twilight-schema.d.ts","sourceRoot":"","sources":["../../../src/vite/plugins/twilight-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAEV,SAAS,EAIV,MAAM,wBAAwB,CAAC;AA+ThC,2EAA2E;AAC3E,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,SAAS,CAkD3D"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salla.sa/twilight-theme-engine",
3
- "version": "1.0.102",
3
+ "version": "1.0.104",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/providers/NavigationProvider.ts"],"names":[],"mappings":";;;;;;;;AA6BO,IAAM,aAAA,GAAN,cAA4B,KAAA,CAAM;AAAA,EACvC,WAAA,CACS,IAAA,EACA,OAAA,GAAU,KAAA,EACjB;AACA,IAAA,KAAA,CAAM,CAAA,YAAA,EAAe,IAAI,CAAA,CAAE,CAAA;AAHpB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AACA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAGP,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AAAA,EACd;AACF;AAGO,IAAM,aAAA,GAAN,cAA4B,KAAA,CAAM;AAAA,EACvC,YAAY,OAAA,EAAkB;AAC5B,IAAA,KAAA,CAAM,WAAW,WAAW,CAAA;AAC5B,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AAAA,EACd;AACF;AAGO,IAAM,iBAAA,GAAN,cAAgC,KAAA,CAAM;AAAA,EAC3C,YAAY,OAAA,EAAkB;AAC5B,IAAA,KAAA,CAAM,WAAW,cAAc,CAAA;AAC/B,IAAA,IAAA,CAAK,IAAA,GAAO,mBAAA;AAAA,EACd;AACF;AAIO,IAAM,eAAA,GAA8B,CAAC,EAAA,EAAI,IAAA,KAAS;AACvD,EAAA,IAAI,IAAA,EAAM,OAAA,EAAS,MAAA,CAAO,QAAA,CAAS,QAAQ,EAAE,CAAA;AAAA,OACxC,MAAA,CAAO,SAAS,IAAA,GAAO,EAAA;AAC9B;AASO,IAAM,eAAA,GAAkB,CAAC,IAAA,EAAc,IAAA,KAAkC;AAC9E,EAAA,MAAM,OAAA,GAAU,MAAM,OAAA,IAAW,KAAA;AAGjC,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,IAAA,IAAI,OAAA,EAAS,MAAA,CAAO,QAAA,CAAS,OAAA,CAAQ,IAAI,CAAA;AAAA,SACpC,MAAA,CAAO,SAAS,IAAA,GAAO,IAAA;AAAA,EAC9B;AAEA,EAAA,MAAM,IAAI,aAAA,CAAc,IAAA,EAAM,OAAO,CAAA;AACvC,CAAA;AAGO,IAAM,eAAA,GAAkB,CAAC,OAAA,KAA4B;AAC1D,EAAA,MAAM,IAAI,cAAc,OAAO,CAAA;AACjC,CAAA;AAGO,IAAM,mBAAA,GAAsB,CAAC,OAAA,KAA4B;AAC9D,EAAA,MAAM,IAAI,kBAAkB,OAAO,CAAA;AACrC,CAAA;AAYA,IAAM,YAAA,mBAAe,MAAA,CAAO,GAAA,CAAI,oCAAoC,CAAA;AACpE,IAAM,QAAA,GAAW,UAAA;AACjB,IAAM,QAAA,GAAgC,QAAA,CAAS,YAAY,CAAA,KAAM;AAAA,EAC/D,QAAA,EAAU,eAAA;AAAA,EACV,QAAA,EAAU,eAAA;AAAA,EACV,YAAA,EAAc;AAChB,CAAA;AAcO,SAAS,SAAS,OAAA,EAAyB;AAChD,EAAA,OAAO,QAAA,CAAS,SAAS,OAAO,CAAA;AAClC;AAaO,SAAS,aAAa,OAAA,EAAyB;AACpD,EAAA,OAAO,QAAA,CAAS,aAAa,OAAO,CAAA;AACtC;AAiBO,SAAS,QAAA,CAAS,MAAc,IAAA,EAA+B;AACpE,EAAA,OAAO,QAAA,CAAS,QAAA,CAAS,IAAA,EAAM,IAAI,CAAA;AACrC;AAMO,SAAS,oBAAoB,MAAA,EAI3B;AACP,EAAA,IAAI,MAAA,CAAO,QAAA,EAAU,QAAA,CAAS,QAAA,GAAW,MAAA,CAAO,QAAA;AAChD,EAAA,IAAI,MAAA,CAAO,QAAA,EAAU,QAAA,CAAS,QAAA,GAAW,MAAA,CAAO,QAAA;AAChD,EAAA,IAAI,MAAA,CAAO,YAAA,EAAc,QAAA,CAAS,YAAA,GAAe,MAAA,CAAO,YAAA;AAC1D;AAcA,eAAsB,QAAW,OAAA,EAAiC;AAChE,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,OAAA;AAAA,EACf,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,kBAAkB,KAAK,CAAA;AACrC,IAAA,MAAM,MAAA,GAAU,OAAyD,QAAA,EAAU,MAAA;AAEnF,IAAA,IAAI,MAAA,KAAW,GAAA,IAAO,MAAA,KAAW,GAAA,SAAY,QAAA,EAAS;AACtD,IAAA,MAAM,KAAA;AAAA,EACR;AACF;AAWA,eAAsB,eAAkB,OAAA,EAAiC;AACvE,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,OAAA;AAAA,EACf,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,MAAA,GAAU,OAAyD,QAAA,EAAU,MAAA;AACnF,IAAA,IAAI,MAAA,KAAW,GAAA,IAAO,MAAA,KAAW,GAAA,EAAK;AACpC,MAAA,MAAM,YAAA,EAAa;AAAA,IACrB;AACA,IAAA,MAAM,KAAA;AAAA,EACR;AACF;AAQA,IAAM,oBAAoB,aAAA,CAAsC;AAAA,EAC9D,QAAA,EAAU;AACZ,CAAC,CAAA;AAEM,SAAS,kBAAA,CAAmB;AAAA,EACjC,QAAA;AAAA,EACA;AACF,CAAA,EAGG;AACD,EAAA,OAAO,aAAA,CAAc,kBAAkB,QAAA,EAAU,EAAE,OAAO,EAAE,QAAA,EAAS,EAAE,EAAG,QAAQ,CAAA;AACpF;AAiBO,SAAS,WAAA,GAA0B;AACxC,EAAA,OAAO,UAAA,CAAW,iBAAiB,CAAA,CAAE,QAAA;AACvC;AAcO,SAAS,UAAA,GAAqB;AACnC,EAAA,OAAO,oBAAA;AAAA,IACL,iBAAA;AAAA,IACA,MAAM,oBAAmB,CAAE,OAAA;AAAA,IAC3B,MAAM,oBAAmB,CAAE;AAAA,GAC7B;AACF;AAmBO,SAAS,WAAA,GAA4E;AAC1F,EAAA,WAAA,EAAY;AACZ,EAAA,OAAO,oBAAmB,CAAE,QAAA;AAC9B;AAMO,SAAS,SAAA,GAAqB;AACnC,EAAA,OAAO,UAAA,OAAiB,OAAA,CAAQ,KAAA;AAClC;AAGO,SAAS,YAAA,GAAwB;AACtC,EAAA,OAAO,UAAA,OAAiB,OAAA,CAAQ,cAAA;AAClC;AAGO,SAAS,SAAA,GAAqB;AACnC,EAAA,OAAO,UAAA,OAAiB,OAAA,CAAQ,IAAA;AAClC;AAGO,SAAS,aAAA,GAAyB;AACvC,EAAA,OAAO,UAAA,EAAW,CAAE,UAAA,CAAW,UAAU,CAAA;AAC3C;AAGO,SAAS,SAAA,GAAqB;AACnC,EAAA,MAAM,UAAU,UAAA,EAAW;AAC3B,EAAA,OAAO,OAAA,KAAY,OAAA,CAAQ,UAAA,IAAc,OAAA,KAAY,OAAA,CAAQ,WAAA;AAC/D;AAGO,SAAS,WAAA,GAAuB;AACrC,EAAA,MAAM,UAAU,UAAA,EAAW;AAC3B,EAAA,OAAO,OAAA,KAAY,OAAA,CAAQ,YAAA,IAAgB,OAAA,KAAY,OAAA,CAAQ,aAAA;AACjE;AAGO,SAAS,WAAA,GAAuB;AACrC,EAAA,OAAO,UAAA,OAAiB,OAAA,CAAQ,MAAA;AAClC;AAUO,SAAS,qBAAA,GAA8B;AAC5C,EAAA,MAAM,WAAW,WAAA,EAAY;AAC7B,EAAA,MAAM,EAAE,KAAA,EAAM,GAAI,WAAA,EAAY;AAC9B,EAAA,wBAAA,CAAyB,QAAA,EAAU,KAAA,EAAO,GAAA,EAAK,KAAA,EAAO,QAAQ,CAAA;AAC9D,EAAA,OAAO,IAAA;AACT;AAmBO,SAAS,mBAAA,CACd,IAAA,EACA,QAAA,EACA,QAAA,EACe;AACf,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,IAAI,GAAA,CAAI,IAAA,EAAM,MAAA,CAAO,SAAS,IAAI,CAAA;AACjD,IAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,QAAQ,CAAA;AAE7B,IAAA,IAAI,MAAA,CAAO,MAAA,KAAW,IAAA,CAAK,MAAA,EAAQ,OAAO,IAAA;AAE1C,IAAA,MAAM,WAAW,mBAAA,CAAoB,MAAA,CAAO,QAAA,EAAU,IAAA,CAAK,UAAU,QAAQ,CAAA;AAC7E,IAAA,MAAM,IAAA,GAAO,QAAA,GAAW,MAAA,CAAO,MAAA,GAAS,MAAA,CAAO,IAAA;AAC/C,IAAA,OAAO,IAAA,IAAQ,GAAA;AAAA,EACjB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAKA,IAAM,mCAAmB,IAAI,GAAA,CAAI,CAAC,QAAA,EAAU,SAAA,EAAW,MAAM,CAAC,CAAA;AAYvD,SAAS,eAAA,CAAgB,QAA2B,KAAA,EAA4B;AACrF,EAAA,IAAI,KAAA,CAAM,kBAAkB,OAAO,KAAA;AAEnC,EAAA,IAAI,KAAA,CAAM,WAAW,KAAA,CAAM,OAAA,IAAW,MAAM,QAAA,IAAY,KAAA,CAAM,QAAQ,OAAO,KAAA;AAE7E,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,YAAA,CAAa,QAAQ,CAAA;AAC/C,EAAA,IAAI,UAAA,IAAc,gBAAA,CAAiB,GAAA,CAAI,UAAU,GAAG,OAAO,KAAA;AAE3D,EAAA,IAAI,MAAA,CAAO,YAAA,CAAa,UAAU,CAAA,EAAG,OAAO,KAAA;AAE5C,EAAA,MAAM,OAAO,MAAA,CAAO,YAAA,CAAa,KAAK,CAAA,IAAK,EAAA,EAAI,MAAM,KAAK,CAAA;AAC1D,EAAA,IAAI,GAAA,CAAI,QAAA,CAAS,UAAU,CAAA,EAAG,OAAO,KAAA;AAErC,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,YAAA,CAAa,MAAM,CAAA,IAAK,EAAA;AAC5C,EAAA,IAAI,CAAC,MAAM,OAAO,KAAA;AAElB,EAAA,IAAI;AACF,IAAA,MAAM,MAAM,IAAI,GAAA,CAAI,IAAA,EAAM,MAAA,CAAO,SAAS,IAAI,CAAA;AAC9C,IAAA,IAAI,GAAA,CAAI,QAAA,CAAS,UAAA,CAAW,aAAa,GAAG,OAAO,KAAA;AAAA,EACrD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,OAAO,IAAA;AACT;AAUO,SAAS,cAAc,IAAA,EAAuB;AACnD,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,IAAI,GAAA,CAAI,IAAA,EAAM,MAAA,CAAO,SAAS,IAAI,CAAA;AAAA,EAC1C,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,MAAM,SAAA,GAAY,mBAAA,CAAoB,GAAA,CAAI,IAAI,CAAA;AAC9C,EAAA,IAAI,CAAC,WAAW,OAAO,KAAA;AACvB,EAAA,MAAM,SAAS,cAAA,EAAe;AAC9B,EAAA,IAAI,SAAA,CAAU,EAAA,KAAO,MAAA,EAAQ,EAAA,EAAI,OAAO,IAAA;AACxC,EAAA,OACE,SAAA,CAAU,iBAAiB,IAAA,KAC1B,SAAA,CAAU,kBAAkB,MAAA,CAAO,aAAA,IAClC,SAAA,CAAU,eAAA,KAAoB,MAAA,CAAO,eAAA,CAAA;AAE3C;AAOO,SAAS,WAAA,CACd,MAAA,EACA,KAAA,EACA,QAAA,EACS;AACT,EAAA,IAAI,MAAM,gBAAA,IAAoB,MAAA,CAAO,YAAA,CAAa,UAAU,GAAG,OAAO,KAAA;AACtE,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,IAAI,IAAI,MAAA,CAAO,YAAA,CAAa,MAAM,CAAA,IAAK,EAAA,EAAI,MAAA,CAAO,QAAA,CAAS,IAAI,CAAA;AAAA,EACvE,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,IAAI,IAAI,QAAA,KAAa,OAAA,IAAW,GAAA,CAAI,QAAA,KAAa,UAAU,OAAO,KAAA;AAClE,EAAA,IAAI,GAAA,CAAI,MAAA,KAAW,MAAA,CAAO,QAAA,CAAS,QAAQ,OAAO,KAAA;AAClD,EAAA,IAAI;AACF,IAAA,OAAO,CAAC,QAAA,IAAY,GAAA,CAAI,WAAW,IAAI,GAAA,CAAI,QAAQ,CAAA,CAAE,MAAA;AAAA,EACvD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEA,SAAS,WAAW,IAAA,EAAuB;AACzC,EAAA,MAAM,MAAM,IAAI,GAAA,CAAI,IAAA,EAAM,MAAA,CAAO,SAAS,IAAI,CAAA;AAC9C,EAAA,OAAO,GAAA,CAAI,aAAa,MAAA,CAAO,QAAA,CAAS,YAAY,GAAA,CAAI,MAAA,KAAW,OAAO,QAAA,CAAS,MAAA;AACrF;AAEA,SAAS,oBAAoB,IAAA,EAA2B;AACtD,EAAA,MAAM,QAAQ,IAAA,CAAK,IAAA;AAAA,IACjB,CAAC,EAAA,KACC,EAAA,YAAc,WAAA,IAAe,GAAG,SAAA,KAAc;AAAA,GAClD;AACA,EAAA,KAAK,OAAO,KAAA,IAAQ;AACtB;AAQO,SAAS,wBAAA,CACd,QAAA,EACA,QAAA,EACA,QAAA,EACM;AACN,EAAA,MAAM,WAAA,GAAc,OAA2B,QAAQ,CAAA;AACvD,EAAA,MAAM,WAAA,GAAc,OAA2B,QAAQ,CAAA;AAEvD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,WAAA,CAAY,OAAA,GAAU,QAAA;AACtB,IAAA,WAAA,CAAY,OAAA,GAAU,QAAA;AAAA,EACxB,CAAA,EAAG,CAAC,QAAA,EAAU,QAAQ,CAAC,CAAA;AAEvB,EAAA,MAAM,WAAA,GAAc,WAAA;AAAA,IAClB,CAAC,IAAA,EAAc,OAAA,GAAU,KAAA,KAAmB;AAC1C,MAAA,MAAM,kBAAkB,WAAA,CAAY,OAAA;AACpC,MAAA,IAAI,CAAC,eAAA,IAAmB,aAAA,CAAc,IAAI,GAAG,OAAO,KAAA;AAEpD,MAAA,MAAM,YAAA,GAAe,mBAAA,CAAoB,IAAA,EAAM,eAAA,EAAiB,YAAY,OAAO,CAAA;AACnF,MAAA,IAAI,CAAC,cAAc,OAAO,KAAA;AAE1B,MAAA,QAAA,CAAS,YAAA,EAAc,EAAE,OAAA,EAAS,CAAA;AAClC,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IACA,CAAC,QAAQ;AAAA,GACX;AAEA,EAAA,SAAA,CAAU,MAAM;AAGd,IAAA,IAAI,aAAA,GAAgB,CAAA;AACpB,IAAA,IAAI,aAAA,GAAgB,CAAA;AACpB,IAAA,IAAI,aAAA,GAAgB,KAAA;AACpB,IAAA,MAAM,cAAA,GAAiB,EAAA;AAEvB,IAAA,SAAS,kBAAkB,KAAA,EAA2B;AACpD,MAAA,aAAA,GAAgB,KAAA,CAAM,OAAA;AACtB,MAAA,aAAA,GAAgB,KAAA,CAAM,OAAA;AACtB,MAAA,aAAA,GAAgB,KAAA;AAAA,IAClB;AAEA,IAAA,SAAS,gBAAgB,KAAA,EAA2B;AAClD,MAAA,MAAM,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,UAAU,aAAa,CAAA;AACjD,MAAA,MAAM,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,UAAU,aAAa,CAAA;AACjD,MAAA,aAAA,GAAgB,EAAA,GAAK,kBAAkB,EAAA,GAAK,cAAA;AAAA,IAC9C;AAGA,IAAA,SAAS,YAAY,KAAA,EAAyB;AAE5C,MAAA,IAAI,aAAA,EAAe;AACjB,QAAA,aAAA,GAAgB,KAAA;AAChB,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,IAAA,GAAO,MAAM,YAAA,EAAa;AAChC,MAAA,MAAM,SAAS,IAAA,CAAK,IAAA,CAAK,CAAC,EAAA,KAAgC,cAAc,iBAAiB,CAAA;AAIzF,MAAA,IACE,MAAA,IACA,WAAA,CAAY,MAAA,EAAQ,KAAA,EAAO,WAAA,CAAY,OAAO,CAAA,IAC9C,iBAAA,CAAkB,MAAA,CAAO,IAAI,CAAA,EAC7B;AACA,QAAA,KAAA,CAAM,cAAA,EAAe;AACrB,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,CAAC,MAAA,IAAU,CAAC,eAAA,CAAgB,MAAA,EAAQ,KAAK,CAAA,EAAG;AAEhD,MAAA,MAAM,QAAA,GAAW,UAAA,CAAW,MAAA,CAAO,IAAI,CAAA;AACvC,MAAA,IAAI,WAAA,CAAY,MAAA,CAAO,IAAA,EAAM,KAAK,CAAA,EAAG;AACnC,QAAA,KAAA,CAAM,cAAA,EAAe;AAErB,QAAA,IAAI,CAAC,QAAA,EAAU,mBAAA,CAAoB,IAAI,CAAA;AAAA,MACzC;AAAA,IACF;AAGA,IAAA,MAAM,UAAA,GAAa,OAAO,QAAA,CAAS,MAAA;AACnC,IAAA,SAAS,cAAc,GAAA,EAAmB;AACxC,MAAA,IAAI,CAAC,YAAY,GAAA,EAAK,KAAK,GAAG,UAAA,CAAW,IAAA,CAAK,MAAA,CAAO,QAAA,EAAU,GAAG,CAAA;AAAA,IACpE;AAGA,IAAA,MAAM,WAAA,GAAc,OAAO,QAAA,CAAS,OAAA;AACpC,IAAA,SAAS,eAAe,GAAA,EAAmB;AACzC,MAAA,IAAI,CAAC,YAAY,GAAA,EAAK,IAAI,GAAG,WAAA,CAAY,IAAA,CAAK,MAAA,CAAO,QAAA,EAAU,GAAG,CAAA;AAAA,IACpE;AAEA,IAAA,IAAI,aAAA,GAAgB,KAAA;AACpB,IAAA,IAAI,cAAA,GAAiB,KAAA;AACrB,IAAA,IAAI;AACF,MAAA,MAAA,CAAO,SAAS,MAAA,GAAS,aAAA;AACzB,MAAA,aAAA,GAAgB,IAAA;AAAA,IAClB,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,IAAI;AACF,MAAA,MAAA,CAAO,SAAS,OAAA,GAAU,cAAA;AAC1B,MAAA,cAAA,GAAiB,IAAA;AAAA,IACnB,CAAA,CAAA,MAAQ;AAAA,IAER;AAEA,IAAA,QAAA,CAAS,iBAAiB,OAAA,EAAS,WAAA,EAAa,EAAE,OAAA,EAAS,MAAM,CAAA;AACjE,IAAA,QAAA,CAAS,iBAAiB,aAAA,EAAe,iBAAA,EAAmB,EAAE,OAAA,EAAS,MAAM,CAAA;AAC7E,IAAA,QAAA,CAAS,iBAAiB,WAAA,EAAa,eAAA,EAAiB,EAAE,OAAA,EAAS,MAAM,CAAA;AAEzE,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,oBAAoB,OAAA,EAAS,WAAA,EAAa,EAAE,OAAA,EAAS,MAAM,CAAA;AACpE,MAAA,QAAA,CAAS,mBAAA,CAAoB,eAAe,iBAAiB,CAAA;AAC7D,MAAA,QAAA,CAAS,mBAAA,CAAoB,aAAa,eAAe,CAAA;AACzD,MAAA,IAAI,aAAA,EAAe;AACjB,QAAA,IAAI;AACF,UAAA,MAAA,CAAO,SAAS,MAAA,GAAS,UAAA;AAAA,QAC3B,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AACA,MAAA,IAAI,cAAA,EAAgB;AAClB,QAAA,IAAI;AACF,UAAA,MAAA,CAAO,SAAS,OAAA,GAAU,WAAA;AAAA,QAC5B,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,WAAW,CAAC,CAAA;AAClB","file":"chunk-GT2L5IJ4.js","sourcesContent":["import {\n createElement,\n createContext,\n useContext,\n useCallback,\n useRef,\n useEffect,\n useSyncExternalStore,\n type ReactNode,\n} from 'react';\nimport { useTwilight } from './twilight-context';\nimport { getTwilightContext, subscribeTwilight, type TwilightLocation } from '../twilight/context';\nimport { RouteId } from '../router/route-ids';\nimport { withoutStoreUrlBase } from '../utils/store-base';\nimport { extractScopeFromUrl } from '../utils/cookies';\nimport { getActiveScope } from '../api/client';\nimport { openNativeBrowser } from '../native-app';\n\n// Re-export RouteId from centralized location\nexport { RouteId } from '../router/route-ids';\nexport type { RouteIdType } from '../router/route-ids';\n\n// Re-export TwilightLocation as Location for convenience\nexport type { TwilightLocation as Location } from '../twilight/context';\n\nexport type NavigateOptions = { replace?: boolean };\nexport type NavigateFn = (to: string, opts?: NavigateOptions) => void;\n\n/** Redirect error - thrown to trigger a redirect */\nexport class RedirectError extends Error {\n constructor(\n public path: string,\n public replace = false\n ) {\n super(`Redirect to ${path}`);\n this.name = 'RedirectError';\n }\n}\n\n/** NotFound error - thrown to trigger 404 */\nexport class NotFoundError extends Error {\n constructor(message?: string) {\n super(message ?? 'Not Found');\n this.name = 'NotFoundError';\n }\n}\n\n/** Unauthorized error - thrown to trigger 401 */\nexport class UnauthorizedError extends Error {\n constructor(message?: string) {\n super(message ?? 'Unauthorized');\n this.name = 'UnauthorizedError';\n }\n}\n\nexport { SettingsError } from '../utils/errors';\n\nexport const defaultNavigate: NavigateFn = (to, opts) => {\n if (opts?.replace) window.location.replace(to);\n else window.location.href = to;\n};\n\nexport interface RedirectOptions {\n replace?: boolean;\n /** HTTP status of a server redirect, e.g. 301 for a URL that moved for good. Defaults to 307. */\n statusCode?: number;\n}\n\n/** Default redirect - throws RedirectError with browser navigation as fallback */\nexport const defaultRedirect = (path: string, opts?: RedirectOptions): never => {\n const replace = opts?.replace ?? false;\n\n // In browser, perform actual navigation before throwing\n if (typeof window !== 'undefined') {\n if (replace) window.location.replace(path);\n else window.location.href = path;\n }\n\n throw new RedirectError(path, replace);\n};\n\n/** Default notFound - throws generic error */\nexport const defaultNotFound = (message?: string): never => {\n throw new NotFoundError(message);\n};\n\n/** Default unauthorized - throws generic error */\nexport const defaultUnauthorized = (message?: string): never => {\n throw new UnauthorizedError(message);\n};\n\n// ─── Framework-agnostic functions for loaders (outside React context) ──────\n\ninterface NavigationHandlers {\n notFound: (message?: string) => never;\n redirect: (path: string, opts?: RedirectOptions) => never;\n unauthorized: (message?: string) => never;\n}\n\n// One set per isolate, so a loader in another copy of this module (a separate\n// package entry, a dev reload) still throws what the framework adapter configured.\nconst HANDLERS_KEY = Symbol.for('salla.twilight.navigation.handlers');\nconst registry = globalThis as { [HANDLERS_KEY]?: NavigationHandlers };\nconst handlers: NavigationHandlers = (registry[HANDLERS_KEY] ??= {\n notFound: defaultNotFound,\n redirect: defaultRedirect,\n unauthorized: defaultUnauthorized,\n});\n\n/**\n * Throw a notFound error. Use in route loaders.\n * Framework adapters will override this to throw framework-specific errors.\n *\n * @example\n * ```ts\n * // In loader\n * import { notFound } from '@salla.sa/twilight-theme-engine/providers';\n *\n * if (!data) throw notFound();\n * ```\n */\nexport function notFound(message?: string): never {\n return handlers.notFound(message);\n}\n\n/**\n * Throw an unauthorized error. Use in route loaders to protect authenticated routes.\n * Framework adapters will override this to throw framework-specific errors.\n *\n * @example\n * ```ts\n * import { unauthorized } from '@salla.sa/twilight-theme-engine/providers';\n *\n * if (!user) throw unauthorized();\n * ```\n */\nexport function unauthorized(message?: string): never {\n return handlers.unauthorized(message);\n}\n\n/**\n * Throw a redirect. Use in route loaders.\n * Framework adapters will override this to throw framework-specific redirects.\n *\n * @param path - Path to redirect to\n * @param opts - Redirect options\n *\n * @example\n * ```ts\n * // In loader\n * import { redirect } from '@salla.sa/twilight-theme-engine/providers';\n *\n * throw redirect('/ar/cart');\n * ```\n */\nexport function redirect(path: string, opts?: RedirectOptions): never {\n return handlers.redirect(path, opts);\n}\n\n/**\n * Configure navigation functions for a specific framework.\n * Called by framework adapters during setup.\n */\nexport function configureNavigation(config: {\n notFound?: (message?: string) => never;\n redirect?: (path: string, opts?: RedirectOptions) => never;\n unauthorized?: (_message?: string) => never;\n}): void {\n if (config.notFound) handlers.notFound = config.notFound;\n if (config.redirect) handlers.redirect = config.redirect;\n if (config.unauthorized) handlers.unauthorized = config.unauthorized;\n}\n\n// ─── Loader Error Handling Helpers ─────────────────────────────────────────────\n\n/**\n * Wraps an API promise with error handling for route loaders.\n * On a 404/410 response throws notFound(); other errors propagate.\n *\n * @example\n * ```ts\n * findOrThrow: (id, locale) => orThrow(product.find(id, locale)),\n * const data = await product.findOrThrow(id, locale);\n * ```\n */\nexport async function orThrow<T>(promise: Promise<T>): Promise<T> {\n try {\n return await promise;\n } catch (error) {\n console.debug('[loader error]', error);\n const status = (error as unknown as { response?: { status?: number } })?.response?.status;\n // The API answers a missing resource with 410, sometimes 404.\n if (status === 404 || status === 410) return notFound();\n throw error;\n }\n}\n\n/**\n * Wraps an API promise with error handling for authenticated route loaders.\n * On a 401/403 response throws unauthorized(); other errors propagate.\n *\n * @example\n * ```ts\n * const data = await orUnauthorized(order.find(id, locale));\n * ```\n */\nexport async function orUnauthorized<T>(promise: Promise<T>): Promise<T> {\n try {\n return await promise;\n } catch (error) {\n const status = (error as unknown as { response?: { status?: number } })?.response?.status;\n if (status === 401 || status === 403) {\n throw unauthorized();\n }\n throw error;\n }\n}\n\n// ─── Navigation Context ──────────────────────────────────────────────────────\n\ninterface NavigationContextValue {\n navigate: NavigateFn;\n}\n\nconst NavigationContext = createContext<NavigationContextValue>({\n navigate: defaultNavigate,\n});\n\nexport function NavigationProvider({\n navigate,\n children,\n}: {\n navigate: NavigateFn;\n children: ReactNode;\n}) {\n return createElement(NavigationContext.Provider, { value: { navigate } }, children);\n}\n\n// ─── Primary Hooks (High Compatibility) ───────────────────────────────────────\n\n/**\n * Get the navigate function.\n * Matches React Router, TanStack Router, and Remix naming convention.\n *\n * @returns Navigate function\n *\n * @example\n * ```tsx\n * const navigate = useNavigate();\n * navigate('/cart');\n * navigate('/cart', { replace: true });\n * ```\n */\nexport function useNavigate(): NavigateFn {\n return useContext(NavigationContext).navigate;\n}\n\n/**\n * Get the current route ID.\n * Used for route detection (isHome, isProduct, etc.)\n *\n * @returns Current route ID string\n *\n * @example\n * ```tsx\n * const routeId = useRouteId();\n * if (routeId === RouteId.INDEX) { ... }\n * ```\n */\nexport function useRouteId(): string {\n return useSyncExternalStore(\n subscribeTwilight,\n () => getTwilightContext().routeId,\n () => getTwilightContext().routeId\n );\n}\n\n/**\n * Get the current location (TanStack Router compatible).\n * Reads from the router context for SSR compatibility.\n *\n * @returns Location object matching TanStack's ParsedLocation\n *\n * @example\n * ```tsx\n * const location = useLocation();\n * console.log(location.pathname); // '/ar/products'\n * console.log(location.searchStr); // '?q=shoes&page=2'\n * console.log(location.search); // { q: 'shoes', page: '2' }\n * console.log(location.href); // 'https://store.com/ar/products?q=shoes'\n * console.log(location.hash); // '#section-1'\n * console.log(location.state); // { scrollY: 100 }\n * ```\n */\nexport function useLocation<TSearch = Record<string, unknown>>(): TwilightLocation<TSearch> {\n useTwilight();\n return getTwilightContext().location as TwilightLocation<TSearch>;\n}\n\n// ─── Selector Hooks ───────────────────────────────────────────────────────────\n\n/**\n * Check if current page is homepage */\nexport function useIsHome(): boolean {\n return useRouteId() === RouteId.INDEX;\n}\n\n/** Check if current page is product detail */\nexport function useIsProduct(): boolean {\n return useRouteId() === RouteId.PRODUCT_SINGLE;\n}\n\n/** Check if current page is cart */\nexport function useIsCart(): boolean {\n return useRouteId() === RouteId.CART;\n}\n\n/** Check if current page is in customer area */\nexport function useIsCustomer(): boolean {\n return useRouteId().startsWith('customer');\n}\n\n/** Check if current page is blog related */\nexport function useIsBlog(): boolean {\n const routeId = useRouteId();\n return routeId === RouteId.BLOG_INDEX || routeId === RouteId.BLOG_SINGLE;\n}\n\n/** Check if current page is brands related */\nexport function useIsBrands(): boolean {\n const routeId = useRouteId();\n return routeId === RouteId.BRANDS_INDEX || routeId === RouteId.BRANDS_SINGLE;\n}\n\n/** Check if current page is search */\nexport function useIsSearch(): boolean {\n return useRouteId() === RouteId.SEARCH;\n}\n\n// ─── Navigation Interceptor ──────────────────────────────────────────────────\n\n/**\n * NavigationInterceptor - Framework-agnostic SPA navigation interceptor.\n *\n * Uses navigate function from NavigationProvider context and store URL\n * from TwilightProvider to intercept same-origin navigations.\n */\nexport function NavigationInterceptor(): null {\n const navigate = useNavigate();\n const { store } = useTwilight();\n useNavigationInterceptor(navigate, store?.url, store?.username);\n return null;\n}\n\n/**\n * resolveRelativePath - Resolve href to store-relative path\n *\n * Returns `null` when the URL is not on the same origin as the store,\n * keeping this helper safe against open-redirect misuse.\n *\n * The path is the application's, not the address on Salla's host: a store served\n * under its username there (`https://demostore.salla.sa/ar/dev-…/`) hands out links\n * carrying that segment, and it is removed. On a host where the store is the root\n * of every URL, the router adds its own segment back when it navigates.\n *\n * @param href - The URL to resolve\n * @param storeUrl - The store's base URL\n * @param username - The store's username, which tells that segment apart from a\n * locale spelled the same way (see `withoutStoreUrlBase`)\n * @returns The relative path string, or null if the URL is external\n */\nexport function resolveRelativePath(\n href: string,\n storeUrl: string,\n username?: string | null\n): string | null {\n try {\n const target = new URL(href, window.location.href);\n const base = new URL(storeUrl);\n\n if (target.origin !== base.origin) return null;\n\n const pathname = withoutStoreUrlBase(target.pathname, base.pathname, username);\n const path = pathname + target.search + target.hash;\n return path || '/';\n } catch {\n return null;\n }\n}\n\n/**\n * EXTERNAL_TARGETS - Target attribute values that indicate external navigation\n */\nconst EXTERNAL_TARGETS = new Set(['_blank', '_parent', '_top']);\n\n/**\n * shouldIntercept - Determine if an anchor click should be intercepted by SPA router\n *\n * Follows browser conventions: modifier keys, external targets, downloads,\n * and non-HTTP(S) protocols are left to the browser's default behavior.\n *\n * @param anchor - The anchor element that was clicked\n * @param event - The click event\n * @returns true if the click should be intercepted by the router\n */\nexport function shouldIntercept(anchor: HTMLAnchorElement, event: MouseEvent): boolean {\n if (event.defaultPrevented) return false;\n\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return false;\n\n const targetAttr = anchor.getAttribute('target');\n if (targetAttr && EXTERNAL_TARGETS.has(targetAttr)) return false;\n\n if (anchor.hasAttribute('download')) return false;\n\n const rel = (anchor.getAttribute('rel') ?? '').split(/\\s+/);\n if (rel.includes('external')) return false;\n\n const href = anchor.getAttribute('href') ?? '';\n if (!href) return false;\n\n try {\n const url = new URL(href, window.location.href);\n if (url.protocol.startsWith('javascript:')) return false;\n } catch {\n return false;\n }\n\n return true;\n}\n\n/**\n * Whether `href` switches market: its `?scope=` names another scope than the active one,\n * or the same scope with another branch (`allocation_type` / `allocation_id`).\n *\n * Twig switches market with a full load (the SDK's scopes modal calls\n * `location.replace('?scope=<id>')`), and only a document request lets the server render\n * the new market and record it in the `scope` cookie. Left to the browser, not the router.\n */\nexport function switchesScope(href: string): boolean {\n let url: URL;\n try {\n url = new URL(href, window.location.href);\n } catch {\n return false;\n }\n const requested = extractScopeFromUrl(url.href);\n if (!requested) return false;\n const active = getActiveScope();\n if (requested.id !== active?.id) return true;\n return (\n requested.allocation_id != null &&\n (requested.allocation_id !== active.allocation_id ||\n requested.allocation_type !== active.allocation_type)\n );\n}\n\n/**\n * Whether an untouched tap on `anchor` would load a page off the store: an\n * http(s) link to neither this page's origin nor the store's. `mailto:`, `tel:`\n * and the like are the device's to handle, and are left alone.\n */\nexport function leavesStore(\n anchor: HTMLAnchorElement,\n event: MouseEvent,\n storeUrl: string | undefined\n): boolean {\n if (event.defaultPrevented || anchor.hasAttribute('download')) return false;\n let url: URL;\n try {\n url = new URL(anchor.getAttribute('href') ?? '', window.location.href);\n } catch {\n return false;\n }\n if (url.protocol !== 'http:' && url.protocol !== 'https:') return false;\n if (url.origin === window.location.origin) return false;\n try {\n return !storeUrl || url.origin !== new URL(storeUrl).origin;\n } catch {\n return true;\n }\n}\n\nfunction isSamePage(href: string): boolean {\n const url = new URL(href, window.location.href);\n return url.pathname === window.location.pathname && url.search === window.location.search;\n}\n\nfunction closeEnclosingModal(path: EventTarget[]): void {\n const modal = path.find(\n (el): el is HTMLElement & { close?: () => unknown } =>\n el instanceof HTMLElement && el.localName === 'salla-modal'\n );\n void modal?.close?.();\n}\n\n// ─── Navigation Interceptor Hook (framework-agnostic) ─────────────────────────\n\n/**\n * Hook for navigation interception using framework-agnostic navigate function.\n * Framework adapters call this with their navigate implementation.\n */\nexport function useNavigationInterceptor(\n navigate: NavigateFn,\n storeUrl: string | undefined,\n username?: string\n): void {\n const storeUrlRef = useRef<string | undefined>(storeUrl);\n const usernameRef = useRef<string | undefined>(username);\n\n useEffect(() => {\n storeUrlRef.current = storeUrl;\n usernameRef.current = username;\n }, [storeUrl, username]);\n\n const tryNavigate = useCallback(\n (href: string, replace = false): boolean => {\n const currentStoreUrl = storeUrlRef.current;\n if (!currentStoreUrl || switchesScope(href)) return false;\n\n const relativePath = resolveRelativePath(href, currentStoreUrl, usernameRef.current);\n if (!relativePath) return false;\n\n navigate(relativePath, { replace });\n return true;\n },\n [navigate]\n );\n\n useEffect(() => {\n // ── Pointer movement tracking ────────────────────────────────────────────\n // Detect drag/scroll gestures to avoid intercepting clicks from swipes.\n let pointerStartX = 0;\n let pointerStartY = 0;\n let pointerSwiped = false;\n const MOVE_THRESHOLD = 10;\n\n function handlePointerDown(event: PointerEvent): void {\n pointerStartX = event.clientX;\n pointerStartY = event.clientY;\n pointerSwiped = false;\n }\n\n function handlePointerUp(event: PointerEvent): void {\n const dx = Math.abs(event.clientX - pointerStartX);\n const dy = Math.abs(event.clientY - pointerStartY);\n pointerSwiped = dx > MOVE_THRESHOLD || dy > MOVE_THRESHOLD;\n }\n\n // ── Anchor click interception ────────────────────────────────────────────\n function handleClick(event: MouseEvent): void {\n // Ignore clicks that resulted from swipe/drag gestures.\n if (pointerSwiped) {\n pointerSwiped = false;\n return;\n }\n\n const path = event.composedPath();\n const anchor = path.find((el): el is HTMLAnchorElement => el instanceof HTMLAnchorElement);\n\n // Inside the Salla app, a link that leaves the store opens in the device's\n // browser; loaded in the app's webview it would strand the shopper there.\n if (\n anchor &&\n leavesStore(anchor, event, storeUrlRef.current) &&\n openNativeBrowser(anchor.href)\n ) {\n event.preventDefault();\n return;\n }\n\n if (!anchor || !shouldIntercept(anchor, event)) return;\n\n const samePage = isSamePage(anchor.href);\n if (tryNavigate(anchor.href, false)) {\n event.preventDefault();\n // A page load would close a web component's modal; an in-app navigation leaves it open.\n if (!samePage) closeEnclosingModal(path);\n }\n }\n\n // ── window.location.assign patch ─────────────────────────────────────────\n const origAssign = window.location.assign;\n function patchedAssign(url: string): void {\n if (!tryNavigate(url, false)) origAssign.call(window.location, url);\n }\n\n // ── window.location.replace patch ────────────────────────────────────────\n const origReplace = window.location.replace;\n function patchedReplace(url: string): void {\n if (!tryNavigate(url, true)) origReplace.call(window.location, url);\n }\n\n let assignPatched = false;\n let replacePatched = false;\n try {\n window.location.assign = patchedAssign;\n assignPatched = true;\n } catch {\n /* non-writable in this environment */\n }\n try {\n window.location.replace = patchedReplace;\n replacePatched = true;\n } catch {\n /* non-writable in this environment */\n }\n\n document.addEventListener('click', handleClick, { capture: true });\n document.addEventListener('pointerdown', handlePointerDown, { passive: true });\n document.addEventListener('pointerup', handlePointerUp, { passive: true });\n\n return () => {\n document.removeEventListener('click', handleClick, { capture: true });\n document.removeEventListener('pointerdown', handlePointerDown);\n document.removeEventListener('pointerup', handlePointerUp);\n if (assignPatched) {\n try {\n window.location.assign = origAssign;\n } catch {\n /* ignore */\n }\n }\n if (replacePatched) {\n try {\n window.location.replace = origReplace;\n } catch {\n /* ignore */\n }\n }\n };\n }, [tryNavigate]);\n}\n\n// ─── Client navigation config ─────────────────────────────────────────────────\n\nexport interface ClientNav {\n /** Framework adapter to use for client-side navigation. @default 'tanstack' */\n framework?: 'tanstack' | 'nextjs';\n /**\n * Intercept same-origin `<a>` clicks and `window.location` calls from web\n * components and route them through the framework router.\n * @default true\n */\n interceptLinks?: boolean;\n}\n\n// Framework adapter setups are registered in navigation-setups.ts to avoid circular imports.\n"]}
@@ -1,14 +0,0 @@
1
- import { lazy } from 'react';
2
-
3
- // src/components/cart/lazy.ts
4
- var LazyCartItem = lazy(() => import('./CartItem-AIVN7POE.js').then((m) => ({ default: m.CartItem })));
5
- var LazyCartSummary = lazy(
6
- () => import('./CartSummary-II45KD76.js').then((m) => ({ default: m.CartSummary }))
7
- );
8
- var LazySeoCartWidget = lazy(
9
- () => import('./SeoCartWidget-THR2WPLF.js').then((m) => ({ default: m.SeoCartWidget }))
10
- );
11
-
12
- export { LazyCartItem, LazyCartSummary, LazySeoCartWidget };
13
- //# sourceMappingURL=chunk-JJSQWN5M.js.map
14
- //# sourceMappingURL=chunk-JJSQWN5M.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/dev/schema-types.ts"],"names":[],"mappings":"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","file":"chunk-N45X7D55.js","sourcesContent":["/**\n * Shared, browser-safe types for the dev-mode twilight.json settings/components\n * editor. Produced (in Node) by `buildTwilightSchema` and consumed (in the\n * browser) by the dev store and `DevSettingsWidget`. Kept free of any Node or\n * React imports so both sides can share it.\n */\n\n/** How a single setting/field is rendered in the dev editor. */\nexport type DevFieldKind =\n | 'toggle'\n | 'select'\n | 'text'\n | 'textarea'\n | 'number'\n | 'image'\n | 'collection'\n | 'entities'\n | 'link'\n | 'readonly';\n\n/** What a picker can look up in the store (or fall back to samples for). */\nexport type DevLookupSource =\n 'products' | 'categories' | 'brands' | 'blog_articles' | 'blog_categories';\n\n/** How long the editor waits for its frame to answer a store lookup. */\nexport const DEV_LOOKUP_TIMEOUT_MS = 8000;\n\n/**\n * How long a lookup may keep reading further pages: well inside\n * {@link DEV_LOOKUP_TIMEOUT_MS}, so the frame answers with what it has found\n * before the editor stops waiting, and stops fetching once it has answered.\n */\nexport const DEV_LOOKUP_BUDGET_MS = 5000;\n\n/** One thing a picker found. `data` is what gets saved, shaped like the API sends it to a block. */\nexport interface DevLookupItem {\n id: string | number;\n name: string;\n image?: string;\n url?: string;\n data: Record<string, unknown>;\n}\n\nexport interface DevSchemaOption {\n label: string;\n value: string;\n}\n\n/** One twilight.json `conditions` entry: the field shows only while `id`'s value passes. */\nexport interface DevFieldCondition {\n /** The other field's id (inside a collection, without the `<collection>.` prefix). */\n id: string;\n /** `=` (also `==`) or `!=`. Any other operator is ignored, so it never hides a field. */\n operation: string;\n value: unknown;\n}\n\nexport interface DevSchemaField {\n /**\n * twilight.json entry `id` — also the key used for overrides. Inside a\n * collection, the `<collection>.` prefix is dropped (`slides.image` → `image`),\n * matching the rows the API hands a block.\n */\n id: string;\n label: string;\n kind: DevFieldKind;\n /** Default value taken from twilight.json (`null` for readonly fields; rows for a collection). */\n default: unknown;\n /** Present for `select`. */\n options?: DevSchemaOption[];\n /** For `readonly`: why it can't be edited yet (e.g. \"collection\", \"remote\"). */\n note?: string;\n /** twilight.json `description`, shown under the field. */\n description?: string;\n placeholder?: string;\n /** `number`: `minimum`/`maximum`. `collection`: `minLength`/`maxLength` (item count). */\n min?: number;\n max?: number;\n /** `collection`: the fields of one item. */\n fields?: DevSchemaField[];\n /** `collection`: what one item is called (`item_label`), e.g. \"Slide\". */\n itemLabel?: string;\n /** `entities`: which store list it picks from. */\n source?: Extract<DevLookupSource, 'products' | 'categories' | 'brands'>;\n /** `entities`: more than one (`multichoice`). */\n multiple?: boolean;\n /** `link`: the kinds of link it offers (`sources`), e.g. product, category, external. */\n linkSources?: DevSchemaOption[];\n /** twilight.json `conditions`: the field shows only while every one holds. */\n conditions?: DevFieldCondition[];\n}\n\n/** A select may hold its choice as `[{ value }]`; compare on the bare value. */\nfunction conditionScalar(value: unknown): unknown {\n const first = Array.isArray(value) ? value[0] : value;\n return first && typeof first === 'object' ? (first as { value?: unknown }).value : first;\n}\n\n/**\n * Whether a field should show: true when it has no `conditions`, or when each\n * one holds against `valueOf` (the current value of the field it names, its\n * default included). Values compare as strings, so `true` matches `\"true\"`.\n */\nexport function conditionsMet(\n field: Pick<DevSchemaField, 'conditions'>,\n valueOf: (id: string) => unknown\n): boolean {\n return (field.conditions ?? []).every(({ id, operation, value }) => {\n const equal = String(conditionScalar(valueOf(id))) === String(conditionScalar(value));\n if (operation === '=' || operation === '==') return equal;\n if (operation === '!=') return !equal;\n return true;\n });\n}\n\nexport interface DevSchemaComponent {\n /** e.g. \"home.enhanced-slider\" — the natural component key. */\n path: string;\n /** twilight.json catalog id, sent as a block's `key` like the API does. */\n key?: string;\n title: string;\n /** `title` per language when twilight.json gives `{ ar, en }`. */\n titles?: Record<string, string>;\n /** twilight.json `image`: a preview of the component, shown when adding one. */\n image?: string;\n /** twilight.json `icon`: a Salla icon class, e.g. `sicon-image`. */\n icon?: string;\n fields: DevSchemaField[];\n}\n\nexport interface DevSchema {\n /** twilight.json `name`, per language (a plain string is filed under both). */\n themeName?: Record<string, string>;\n /** Editable + readonly theme settings, in declaration order. */\n settings: DevSchemaField[];\n /** Store components with their fields. */\n components: DevSchemaComponent[];\n /** `{ [settingId]: default }` for every non-readonly setting. */\n settingsDefaults: Record<string, unknown>;\n /** `{ [componentPath]: { [fieldId]: default } }`. */\n componentDefaults: Record<string, Record<string, unknown>>;\n /**\n * `{ [componentPath]: data }`: everything a newly added block starts with,\n * readonly fields included, shaped the way the API delivers block data\n * (collection rows lose their `<collection>.` key prefix). Optional so a\n * schema from an older engine build still type-checks.\n */\n blockDefaults?: Record<string, Record<string, unknown>>;\n /** The saved preview state (`twilight.preview.json`), `null` when there is none. */\n preview?: DevPreviewState | null;\n}\n\n/** One home block in a dev-owned layout. */\nexport interface DevPreviewBlock {\n /** Stable id for React keys and edits; unrelated to the API. */\n id: string;\n /** Home loader spelling, without the `home.` prefix (e.g. \"main-links\"). */\n path: string;\n /** The block's data, spread onto `{ path }` when it renders. */\n fields: Record<string, unknown>;\n}\n\n/**\n * Everything the dev editor saves, persisted to `twilight.preview.json` by the\n * dev server so the server render and every tab start from the same values.\n */\nexport interface DevPreviewState {\n /** Master switch: when false the theme uses the real store's values. */\n enabled: boolean;\n /** Sparse `{ [settingId]: value }` overrides for theme settings. */\n settings: Record<string, unknown>;\n /** The home page's blocks, in order. `null` renders the store's own blocks. */\n layout: DevPreviewBlock[] | null;\n}\n\n/** Dev-server page that hosts the theme editor. */\nexport const DEV_EDITOR_PATH = '/__twilight/editor';\n\n/** Marks the iframe the editor frames the storefront in. */\nexport const DEV_EDITOR_FRAME_ATTR = 'data-twilight-editor';\n\n/** True inside the editor's frame, where the storefront hides its own dev button. */\nexport function isEditorFrame(): boolean {\n if (typeof window === 'undefined') return false;\n try {\n return window.frameElement?.hasAttribute(DEV_EDITOR_FRAME_ATTR) ?? false;\n } catch {\n return false; // Framed by another origin: not our editor.\n }\n}\n\n/** Dev-server endpoint the editor saves through. */\nexport const DEV_PREVIEW_ENDPOINT = '/__twilight/preview';\n\n/**\n * Where a picked image goes: the dev server keeps it in `twilight-preview-assets/`\n * (gitignored, next to twilight.json) and serves it back from under this path,\n * so the saved state holds a short URL rather than the image itself.\n */\nexport const DEV_PREVIEW_IMAGE_ENDPOINT = `${DEV_PREVIEW_ENDPOINT}/image`;\nexport const DEV_PREVIEW_IMAGE_MAX_BYTES = 5 * 1024 * 1024;\n\n/** Dev-server event that hands a save to the other open tabs. */\nexport const DEV_PREVIEW_EVENT = 'twilight:preview';\n\n/** Where `virtual:twilight/schema` puts the saved state before the app renders. */\nexport const DEV_PREVIEW_GLOBAL = '__twilightDevPreview__';\n\nexport const EMPTY_PREVIEW_STATE: DevPreviewState = { enabled: false, settings: {}, layout: null };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Coerce anything (a hand-edited file, a request body) into a valid state, or\n * `null` when it isn't one at all. Blocks without a path are dropped and\n * missing ids are filled, so a bad entry can't break the home page.\n */\nexport function normalizePreviewState(raw: unknown): DevPreviewState | null {\n if (!isRecord(raw)) return null;\n const layout: DevPreviewBlock[] | null = Array.isArray(raw.layout)\n ? raw.layout.flatMap((entry: unknown, index) =>\n isRecord(entry) && typeof entry.path === 'string' && entry.path\n ? [\n {\n id: typeof entry.id === 'string' && entry.id ? entry.id : `block-${index}`,\n path: entry.path.replace(/^home\\./, ''),\n fields: isRecord(entry.fields) ? entry.fields : {},\n },\n ]\n : []\n )\n : null;\n return {\n enabled: raw.enabled === true,\n settings: isRecord(raw.settings) ? raw.settings : {},\n layout,\n };\n}\n\n/** The shape the vite plugin ships when there is no schema (prod / missing file). */\nexport const EMPTY_DEV_SCHEMA: DevSchema = {\n settings: [],\n components: [],\n settingsDefaults: {},\n componentDefaults: {},\n blockDefaults: {},\n preview: null,\n};\n"]}