@aglyn/plugins-commerce 1.0.0-beta.143

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (417) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +10 -0
  3. package/package.json +57 -0
  4. package/src/index.d.ts +38 -0
  5. package/src/index.js +38 -0
  6. package/src/index.js.map +1 -0
  7. package/src/lib/components/account.d.ts +31 -0
  8. package/src/lib/components/account.js +645 -0
  9. package/src/lib/components/account.js.map +1 -0
  10. package/src/lib/components/cart.d.ts +38 -0
  11. package/src/lib/components/cart.js +851 -0
  12. package/src/lib/components/cart.js.map +1 -0
  13. package/src/lib/components/commerce-console-page.d.ts +32 -0
  14. package/src/lib/components/commerce-console-page.js +296 -0
  15. package/src/lib/components/commerce-console-page.js.map +1 -0
  16. package/src/lib/components/commerce-console-sections.d.ts +34 -0
  17. package/src/lib/components/commerce-console-sections.js +62 -0
  18. package/src/lib/components/commerce-console-sections.js.map +1 -0
  19. package/src/lib/components/console/catalog-organization-card.component.d.ts +14 -0
  20. package/src/lib/components/console/catalog-organization-card.component.js +1087 -0
  21. package/src/lib/components/console/catalog-organization-card.component.js.map +1 -0
  22. package/src/lib/components/console/commerce-analytics-card.component.d.ts +27 -0
  23. package/src/lib/components/console/commerce-analytics-card.component.js +310 -0
  24. package/src/lib/components/console/commerce-analytics-card.component.js.map +1 -0
  25. package/src/lib/components/console/commerce-glance-card.component.d.ts +20 -0
  26. package/src/lib/components/console/commerce-glance-card.component.js +340 -0
  27. package/src/lib/components/console/commerce-glance-card.component.js.map +1 -0
  28. package/src/lib/components/console/commerce-stat-tile.component.d.ts +37 -0
  29. package/src/lib/components/console/commerce-stat-tile.component.js +72 -0
  30. package/src/lib/components/console/commerce-stat-tile.component.js.map +1 -0
  31. package/src/lib/components/console/discounts-card.component.d.ts +14 -0
  32. package/src/lib/components/console/discounts-card.component.js +443 -0
  33. package/src/lib/components/console/discounts-card.component.js.map +1 -0
  34. package/src/lib/components/console/entitlement-gate.component.d.ts +76 -0
  35. package/src/lib/components/console/entitlement-gate.component.js +115 -0
  36. package/src/lib/components/console/entitlement-gate.component.js.map +1 -0
  37. package/src/lib/components/console/gift-cards-card.component.d.ts +29 -0
  38. package/src/lib/components/console/gift-cards-card.component.js +379 -0
  39. package/src/lib/components/console/gift-cards-card.component.js.map +1 -0
  40. package/src/lib/components/console/host-coupons-card.component.d.ts +14 -0
  41. package/src/lib/components/console/host-coupons-card.component.js +252 -0
  42. package/src/lib/components/console/host-coupons-card.component.js.map +1 -0
  43. package/src/lib/components/console/host-orders-card.component.d.ts +13 -0
  44. package/src/lib/components/console/host-orders-card.component.js +861 -0
  45. package/src/lib/components/console/host-orders-card.component.js.map +1 -0
  46. package/src/lib/components/console/locations-card.component.d.ts +14 -0
  47. package/src/lib/components/console/locations-card.component.js +256 -0
  48. package/src/lib/components/console/locations-card.component.js.map +1 -0
  49. package/src/lib/components/console/member-posts-card.component.d.ts +8 -0
  50. package/src/lib/components/console/member-posts-card.component.js +283 -0
  51. package/src/lib/components/console/member-posts-card.component.js.map +1 -0
  52. package/src/lib/components/console/newest-site-users-card.component.d.ts +36 -0
  53. package/src/lib/components/console/newest-site-users-card.component.js +126 -0
  54. package/src/lib/components/console/newest-site-users-card.component.js.map +1 -0
  55. package/src/lib/components/console/order-detail-dialog.component.d.ts +28 -0
  56. package/src/lib/components/console/order-detail-dialog.component.js +976 -0
  57. package/src/lib/components/console/order-detail-dialog.component.js.map +1 -0
  58. package/src/lib/components/console/paid-media.d.ts +127 -0
  59. package/src/lib/components/console/paid-media.js +397 -0
  60. package/src/lib/components/console/paid-media.js.map +1 -0
  61. package/src/lib/components/console/payments-settings-card.component.d.ts +13 -0
  62. package/src/lib/components/console/payments-settings-card.component.js +295 -0
  63. package/src/lib/components/console/payments-settings-card.component.js.map +1 -0
  64. package/src/lib/components/console/pos-page.component.d.ts +13 -0
  65. package/src/lib/components/console/pos-page.component.js +916 -0
  66. package/src/lib/components/console/pos-page.component.js.map +1 -0
  67. package/src/lib/components/console/product-editor-dialog.component.d.ts +32 -0
  68. package/src/lib/components/console/product-editor-dialog.component.js +1374 -0
  69. package/src/lib/components/console/product-editor-dialog.component.js.map +1 -0
  70. package/src/lib/components/console/products-hub-card.component.d.ts +16 -0
  71. package/src/lib/components/console/products-hub-card.component.js +1280 -0
  72. package/src/lib/components/console/products-hub-card.component.js.map +1 -0
  73. package/src/lib/components/console/products-hub-zone.component.d.ts +50 -0
  74. package/src/lib/components/console/products-hub-zone.component.js +200 -0
  75. package/src/lib/components/console/products-hub-zone.component.js.map +1 -0
  76. package/src/lib/components/console/recovery-queue-card.component.d.ts +39 -0
  77. package/src/lib/components/console/recovery-queue-card.component.js +262 -0
  78. package/src/lib/components/console/recovery-queue-card.component.js.map +1 -0
  79. package/src/lib/components/console/registers-card.component.d.ts +21 -0
  80. package/src/lib/components/console/registers-card.component.js +296 -0
  81. package/src/lib/components/console/registers-card.component.js.map +1 -0
  82. package/src/lib/components/console/reservations-card.component.d.ts +14 -0
  83. package/src/lib/components/console/reservations-card.component.js +650 -0
  84. package/src/lib/components/console/reservations-card.component.js.map +1 -0
  85. package/src/lib/components/console/reviews-moderation-card.component.d.ts +8 -0
  86. package/src/lib/components/console/reviews-moderation-card.component.js +235 -0
  87. package/src/lib/components/console/reviews-moderation-card.component.js.map +1 -0
  88. package/src/lib/components/console/shipping-settings-card.component.d.ts +38 -0
  89. package/src/lib/components/console/shipping-settings-card.component.js +560 -0
  90. package/src/lib/components/console/shipping-settings-card.component.js.map +1 -0
  91. package/src/lib/components/console/stock-movements-card.component.d.ts +31 -0
  92. package/src/lib/components/console/stock-movements-card.component.js +333 -0
  93. package/src/lib/components/console/stock-movements-card.component.js.map +1 -0
  94. package/src/lib/components/console/store-settings-card.component.d.ts +14 -0
  95. package/src/lib/components/console/store-settings-card.component.js +300 -0
  96. package/src/lib/components/console/store-settings-card.component.js.map +1 -0
  97. package/src/lib/components/console/storefront-tax-summary-card.component.d.ts +73 -0
  98. package/src/lib/components/console/storefront-tax-summary-card.component.js +408 -0
  99. package/src/lib/components/console/storefront-tax-summary-card.component.js.map +1 -0
  100. package/src/lib/components/console/suppliers-card.component.d.ts +8 -0
  101. package/src/lib/components/console/suppliers-card.component.js +328 -0
  102. package/src/lib/components/console/suppliers-card.component.js.map +1 -0
  103. package/src/lib/components/console/tax-settings-card.component.d.ts +14 -0
  104. package/src/lib/components/console/tax-settings-card.component.js +473 -0
  105. package/src/lib/components/console/tax-settings-card.component.js.map +1 -0
  106. package/src/lib/components/gate.d.ts +39 -0
  107. package/src/lib/components/gate.js +202 -0
  108. package/src/lib/components/gate.js.map +1 -0
  109. package/src/lib/components/gated-video.d.ts +40 -0
  110. package/src/lib/components/gated-video.js +366 -0
  111. package/src/lib/components/gated-video.js.map +1 -0
  112. package/src/lib/components/member-feed.d.ts +32 -0
  113. package/src/lib/components/member-feed.js +198 -0
  114. package/src/lib/components/member-feed.js.map +1 -0
  115. package/src/lib/components/member-recovery.d.ts +35 -0
  116. package/src/lib/components/member-recovery.js +313 -0
  117. package/src/lib/components/member-recovery.js.map +1 -0
  118. package/src/lib/components/member-signin.d.ts +35 -0
  119. package/src/lib/components/member-signin.js +257 -0
  120. package/src/lib/components/member-signin.js.map +1 -0
  121. package/src/lib/components/member-signup.d.ts +34 -0
  122. package/src/lib/components/member-signup.js +287 -0
  123. package/src/lib/components/member-signup.js.map +1 -0
  124. package/src/lib/components/newsletter-signup.d.ts +39 -0
  125. package/src/lib/components/newsletter-signup.js +229 -0
  126. package/src/lib/components/newsletter-signup.js.map +1 -0
  127. package/src/lib/components/product-detail.d.ts +38 -0
  128. package/src/lib/components/product-detail.js +1022 -0
  129. package/src/lib/components/product-detail.js.map +1 -0
  130. package/src/lib/components/product-grid.d.ts +67 -0
  131. package/src/lib/components/product-grid.js +909 -0
  132. package/src/lib/components/product-grid.js.map +1 -0
  133. package/src/lib/components/product-reviews.d.ts +32 -0
  134. package/src/lib/components/product-reviews.js +349 -0
  135. package/src/lib/components/product-reviews.js.map +1 -0
  136. package/src/lib/components/related-products.d.ts +33 -0
  137. package/src/lib/components/related-products.js +232 -0
  138. package/src/lib/components/related-products.js.map +1 -0
  139. package/src/lib/components/reservation-widget.d.ts +33 -0
  140. package/src/lib/components/reservation-widget.js +418 -0
  141. package/src/lib/components/reservation-widget.js.map +1 -0
  142. package/src/lib/components/storefront-payment-element-fallback.d.ts +18 -0
  143. package/src/lib/components/storefront-payment-element-fallback.js +51 -0
  144. package/src/lib/components/storefront-payment-element-fallback.js.map +1 -0
  145. package/src/lib/components/storefront-payment-element.d.ts +78 -0
  146. package/src/lib/components/storefront-payment-element.js +156 -0
  147. package/src/lib/components/storefront-payment-element.js.map +1 -0
  148. package/src/lib/components/wishlist.d.ts +46 -0
  149. package/src/lib/components/wishlist.js +304 -0
  150. package/src/lib/components/wishlist.js.map +1 -0
  151. package/src/lib/constants/bundle-common.d.ts +18 -0
  152. package/src/lib/constants/bundle-common.js +18 -0
  153. package/src/lib/constants/bundle-common.js.map +1 -0
  154. package/src/lib/constants/product-filters.d.ts +35 -0
  155. package/src/lib/constants/product-filters.js +109 -0
  156. package/src/lib/constants/product-filters.js.map +1 -0
  157. package/src/lib/model/commerce-cart.d.ts +52 -0
  158. package/src/lib/model/commerce-cart.js +102 -0
  159. package/src/lib/model/commerce-cart.js.map +1 -0
  160. package/src/lib/model/commerce-connect-transfer.d.ts +243 -0
  161. package/src/lib/model/commerce-connect-transfer.js +231 -0
  162. package/src/lib/model/commerce-connect-transfer.js.map +1 -0
  163. package/src/lib/model/commerce-discounts.d.ts +164 -0
  164. package/src/lib/model/commerce-discounts.js +231 -0
  165. package/src/lib/model/commerce-discounts.js.map +1 -0
  166. package/src/lib/model/commerce-dispute.d.ts +124 -0
  167. package/src/lib/model/commerce-dispute.js +225 -0
  168. package/src/lib/model/commerce-dispute.js.map +1 -0
  169. package/src/lib/model/commerce-gift-cards.d.ts +107 -0
  170. package/src/lib/model/commerce-gift-cards.js +121 -0
  171. package/src/lib/model/commerce-gift-cards.js.map +1 -0
  172. package/src/lib/model/commerce-io.d.ts +36 -0
  173. package/src/lib/model/commerce-io.js +245 -0
  174. package/src/lib/model/commerce-io.js.map +1 -0
  175. package/src/lib/model/commerce-orders.d.ts +1040 -0
  176. package/src/lib/model/commerce-orders.js +1022 -0
  177. package/src/lib/model/commerce-orders.js.map +1 -0
  178. package/src/lib/model/commerce-promotions.d.ts +188 -0
  179. package/src/lib/model/commerce-promotions.js +199 -0
  180. package/src/lib/model/commerce-promotions.js.map +1 -0
  181. package/src/lib/model/commerce-reservations.d.ts +175 -0
  182. package/src/lib/model/commerce-reservations.js +157 -0
  183. package/src/lib/model/commerce-reservations.js.map +1 -0
  184. package/src/lib/model/commerce-shipping.d.ts +316 -0
  185. package/src/lib/model/commerce-shipping.js +484 -0
  186. package/src/lib/model/commerce-shipping.js.map +1 -0
  187. package/src/lib/model/commerce-stock-holds.d.ts +199 -0
  188. package/src/lib/model/commerce-stock-holds.js +190 -0
  189. package/src/lib/model/commerce-stock-holds.js.map +1 -0
  190. package/src/lib/model/commerce-subscription-status.d.ts +67 -0
  191. package/src/lib/model/commerce-subscription-status.js +76 -0
  192. package/src/lib/model/commerce-subscription-status.js.map +1 -0
  193. package/src/lib/model/commerce-tax-decision.d.ts +222 -0
  194. package/src/lib/model/commerce-tax-decision.js +165 -0
  195. package/src/lib/model/commerce-tax-decision.js.map +1 -0
  196. package/src/lib/model/commerce-tax.d.ts +176 -0
  197. package/src/lib/model/commerce-tax.js +92 -0
  198. package/src/lib/model/commerce-tax.js.map +1 -0
  199. package/src/lib/model/commerce.d.ts +551 -0
  200. package/src/lib/model/commerce.js +739 -0
  201. package/src/lib/model/commerce.js.map +1 -0
  202. package/src/lib/model/index.d.ts +40 -0
  203. package/src/lib/model/index.js +40 -0
  204. package/src/lib/model/index.js.map +1 -0
  205. package/src/lib/model/order-figures.d.ts +48 -0
  206. package/src/lib/model/order-figures.js +74 -0
  207. package/src/lib/model/order-figures.js.map +1 -0
  208. package/src/lib/model/plugin-permissions.d.ts +23 -0
  209. package/src/lib/model/plugin-permissions.js +34 -0
  210. package/src/lib/model/plugin-permissions.js.map +1 -0
  211. package/src/lib/model/purchase-analytics.d.ts +186 -0
  212. package/src/lib/model/purchase-analytics.js +216 -0
  213. package/src/lib/model/purchase-analytics.js.map +1 -0
  214. package/src/lib/plugin-config.d.ts +62 -0
  215. package/src/lib/plugin-config.js +78 -0
  216. package/src/lib/plugin-config.js.map +1 -0
  217. package/src/lib/plugin.d.ts +28 -0
  218. package/src/lib/plugin.js +147 -0
  219. package/src/lib/plugin.js.map +1 -0
  220. package/src/lib/server/billing-webhook.d.ts +26 -0
  221. package/src/lib/server/billing-webhook.js +4011 -0
  222. package/src/lib/server/billing-webhook.js.map +1 -0
  223. package/src/lib/server/cancel-order.d.ts +87 -0
  224. package/src/lib/server/cancel-order.js +368 -0
  225. package/src/lib/server/cancel-order.js.map +1 -0
  226. package/src/lib/server/cart-checkout.d.ts +25 -0
  227. package/src/lib/server/cart-checkout.js +976 -0
  228. package/src/lib/server/cart-checkout.js.map +1 -0
  229. package/src/lib/server/cart-cookie.d.ts +32 -0
  230. package/src/lib/server/cart-cookie.js +77 -0
  231. package/src/lib/server/cart-cookie.js.map +1 -0
  232. package/src/lib/server/cart.d.ts +34 -0
  233. package/src/lib/server/cart.js +181 -0
  234. package/src/lib/server/cart.js.map +1 -0
  235. package/src/lib/server/catalog.d.ts +127 -0
  236. package/src/lib/server/catalog.js +277 -0
  237. package/src/lib/server/catalog.js.map +1 -0
  238. package/src/lib/server/checkout.d.ts +36 -0
  239. package/src/lib/server/checkout.js +915 -0
  240. package/src/lib/server/checkout.js.map +1 -0
  241. package/src/lib/server/connect.d.ts +26 -0
  242. package/src/lib/server/connect.js +238 -0
  243. package/src/lib/server/connect.js.map +1 -0
  244. package/src/lib/server/contact-refund.d.ts +117 -0
  245. package/src/lib/server/contact-refund.js +196 -0
  246. package/src/lib/server/contact-refund.js.map +1 -0
  247. package/src/lib/server/download.d.ts +39 -0
  248. package/src/lib/server/download.js +206 -0
  249. package/src/lib/server/download.js.map +1 -0
  250. package/src/lib/server/draft-order.d.ts +26 -0
  251. package/src/lib/server/draft-order.js +706 -0
  252. package/src/lib/server/draft-order.js.map +1 -0
  253. package/src/lib/server/feed.d.ts +24 -0
  254. package/src/lib/server/feed.js +59 -0
  255. package/src/lib/server/feed.js.map +1 -0
  256. package/src/lib/server/fulfill-order.d.ts +97 -0
  257. package/src/lib/server/fulfill-order.js +235 -0
  258. package/src/lib/server/fulfill-order.js.map +1 -0
  259. package/src/lib/server/gate.d.ts +36 -0
  260. package/src/lib/server/gate.js +112 -0
  261. package/src/lib/server/gate.js.map +1 -0
  262. package/src/lib/server/gift-cards.d.ts +42 -0
  263. package/src/lib/server/gift-cards.js +219 -0
  264. package/src/lib/server/gift-cards.js.map +1 -0
  265. package/src/lib/server/low-stock.d.ts +49 -0
  266. package/src/lib/server/low-stock.js +60 -0
  267. package/src/lib/server/low-stock.js.map +1 -0
  268. package/src/lib/server/manual-tax-rate.d.ts +82 -0
  269. package/src/lib/server/manual-tax-rate.js +113 -0
  270. package/src/lib/server/manual-tax-rate.js.map +1 -0
  271. package/src/lib/server/member-feed.d.ts +24 -0
  272. package/src/lib/server/member-feed.js +72 -0
  273. package/src/lib/server/member-feed.js.map +1 -0
  274. package/src/lib/server/member-name-search.d.ts +37 -0
  275. package/src/lib/server/member-name-search.js +42 -0
  276. package/src/lib/server/member-name-search.js.map +1 -0
  277. package/src/lib/server/member-post.d.ts +23 -0
  278. package/src/lib/server/member-post.js +166 -0
  279. package/src/lib/server/member-post.js.map +1 -0
  280. package/src/lib/server/membership-account.d.ts +37 -0
  281. package/src/lib/server/membership-account.js +148 -0
  282. package/src/lib/server/membership-account.js.map +1 -0
  283. package/src/lib/server/membership-admin-password.d.ts +33 -0
  284. package/src/lib/server/membership-admin-password.js +202 -0
  285. package/src/lib/server/membership-admin-password.js.map +1 -0
  286. package/src/lib/server/membership-content.d.ts +23 -0
  287. package/src/lib/server/membership-content.js +105 -0
  288. package/src/lib/server/membership-content.js.map +1 -0
  289. package/src/lib/server/membership-login.d.ts +19 -0
  290. package/src/lib/server/membership-login.js +137 -0
  291. package/src/lib/server/membership-login.js.map +1 -0
  292. package/src/lib/server/membership-logout.d.ts +19 -0
  293. package/src/lib/server/membership-logout.js +35 -0
  294. package/src/lib/server/membership-logout.js.map +1 -0
  295. package/src/lib/server/membership-recover.d.ts +60 -0
  296. package/src/lib/server/membership-recover.js +244 -0
  297. package/src/lib/server/membership-recover.js.map +1 -0
  298. package/src/lib/server/membership-register.d.ts +22 -0
  299. package/src/lib/server/membership-register.js +241 -0
  300. package/src/lib/server/membership-register.js.map +1 -0
  301. package/src/lib/server/membership-reset.d.ts +26 -0
  302. package/src/lib/server/membership-reset.js +88 -0
  303. package/src/lib/server/membership-reset.js.map +1 -0
  304. package/src/lib/server/membership-wishlist.d.ts +23 -0
  305. package/src/lib/server/membership-wishlist.js +89 -0
  306. package/src/lib/server/membership-wishlist.js.map +1 -0
  307. package/src/lib/server/membership.d.ts +96 -0
  308. package/src/lib/server/membership.js +222 -0
  309. package/src/lib/server/membership.js.map +1 -0
  310. package/src/lib/server/native-checkout.d.ts +170 -0
  311. package/src/lib/server/native-checkout.js +193 -0
  312. package/src/lib/server/native-checkout.js.map +1 -0
  313. package/src/lib/server/newsletter.d.ts +23 -0
  314. package/src/lib/server/newsletter.js +323 -0
  315. package/src/lib/server/newsletter.js.map +1 -0
  316. package/src/lib/server/notify-restock.d.ts +22 -0
  317. package/src/lib/server/notify-restock.js +84 -0
  318. package/src/lib/server/notify-restock.js.map +1 -0
  319. package/src/lib/server/order-analytics.d.ts +134 -0
  320. package/src/lib/server/order-analytics.js +263 -0
  321. package/src/lib/server/order-analytics.js.map +1 -0
  322. package/src/lib/server/order-figures.d.ts +33 -0
  323. package/src/lib/server/order-figures.js +220 -0
  324. package/src/lib/server/order-figures.js.map +1 -0
  325. package/src/lib/server/paid-media-delivery.d.ts +173 -0
  326. package/src/lib/server/paid-media-delivery.js +212 -0
  327. package/src/lib/server/paid-media-delivery.js.map +1 -0
  328. package/src/lib/server/pos-order.d.ts +54 -0
  329. package/src/lib/server/pos-order.js +1137 -0
  330. package/src/lib/server/pos-order.js.map +1 -0
  331. package/src/lib/server/process-abandoned.d.ts +54 -0
  332. package/src/lib/server/process-abandoned.js +222 -0
  333. package/src/lib/server/process-abandoned.js.map +1 -0
  334. package/src/lib/server/process-restock.d.ts +42 -0
  335. package/src/lib/server/process-restock.js +219 -0
  336. package/src/lib/server/process-restock.js.map +1 -0
  337. package/src/lib/server/product-card.d.ts +29 -0
  338. package/src/lib/server/product-card.js +54 -0
  339. package/src/lib/server/product-card.js.map +1 -0
  340. package/src/lib/server/product.d.ts +70 -0
  341. package/src/lib/server/product.js +105 -0
  342. package/src/lib/server/product.js.map +1 -0
  343. package/src/lib/server/promotion-hold.d.ts +144 -0
  344. package/src/lib/server/promotion-hold.js +174 -0
  345. package/src/lib/server/promotion-hold.js.map +1 -0
  346. package/src/lib/server/reconcile-stock.d.ts +106 -0
  347. package/src/lib/server/reconcile-stock.js +349 -0
  348. package/src/lib/server/reconcile-stock.js.map +1 -0
  349. package/src/lib/server/refund.d.ts +45 -0
  350. package/src/lib/server/refund.js +607 -0
  351. package/src/lib/server/refund.js.map +1 -0
  352. package/src/lib/server/related.d.ts +24 -0
  353. package/src/lib/server/related.js +104 -0
  354. package/src/lib/server/related.js.map +1 -0
  355. package/src/lib/server/reservation-availability.d.ts +23 -0
  356. package/src/lib/server/reservation-availability.js +111 -0
  357. package/src/lib/server/reservation-availability.js.map +1 -0
  358. package/src/lib/server/reserve-stock.d.ts +156 -0
  359. package/src/lib/server/reserve-stock.js +146 -0
  360. package/src/lib/server/reserve-stock.js.map +1 -0
  361. package/src/lib/server/reserve.d.ts +25 -0
  362. package/src/lib/server/reserve.js +426 -0
  363. package/src/lib/server/reserve.js.map +1 -0
  364. package/src/lib/server/restock-flag.d.ts +202 -0
  365. package/src/lib/server/restock-flag.js +449 -0
  366. package/src/lib/server/restock-flag.js.map +1 -0
  367. package/src/lib/server/reviews.d.ts +51 -0
  368. package/src/lib/server/reviews.js +132 -0
  369. package/src/lib/server/reviews.js.map +1 -0
  370. package/src/lib/server/site-page-enricher.d.ts +42 -0
  371. package/src/lib/server/site-page-enricher.js +149 -0
  372. package/src/lib/server/site-page-enricher.js.map +1 -0
  373. package/src/lib/server/site-page-resolver.d.ts +26 -0
  374. package/src/lib/server/site-page-resolver.js +223 -0
  375. package/src/lib/server/site-page-resolver.js.map +1 -0
  376. package/src/lib/server/stock-hold.d.ts +127 -0
  377. package/src/lib/server/stock-hold.js +258 -0
  378. package/src/lib/server/stock-hold.js.map +1 -0
  379. package/src/lib/server/storefront-tax-record.d.ts +22 -0
  380. package/src/lib/server/storefront-tax-record.js +218 -0
  381. package/src/lib/server/storefront-tax-record.js.map +1 -0
  382. package/src/lib/server/storefront-tax.d.ts +197 -0
  383. package/src/lib/server/storefront-tax.js +245 -0
  384. package/src/lib/server/storefront-tax.js.map +1 -0
  385. package/src/lib/server/stream.d.ts +25 -0
  386. package/src/lib/server/stream.js +191 -0
  387. package/src/lib/server/stream.js.map +1 -0
  388. package/src/lib/server/subscription-portal.d.ts +24 -0
  389. package/src/lib/server/subscription-portal.js +91 -0
  390. package/src/lib/server/subscription-portal.js.map +1 -0
  391. package/src/lib/server/supplier-outbox.d.ts +190 -0
  392. package/src/lib/server/supplier-outbox.js +342 -0
  393. package/src/lib/server/supplier-outbox.js.map +1 -0
  394. package/src/lib/server/supplier-update.d.ts +23 -0
  395. package/src/lib/server/supplier-update.js +289 -0
  396. package/src/lib/server/supplier-update.js.map +1 -0
  397. package/src/lib/server/tax-profile.d.ts +29 -0
  398. package/src/lib/server/tax-profile.js +40 -0
  399. package/src/lib/server/tax-profile.js.map +1 -0
  400. package/src/lib/server.d.ts +32 -0
  401. package/src/lib/server.js +311 -0
  402. package/src/lib/server.js.map +1 -0
  403. package/src/lib/site.d.ts +27 -0
  404. package/src/lib/site.js +134 -0
  405. package/src/lib/site.js.map +1 -0
  406. package/src/lib/utils/escape-html.d.ts +41 -0
  407. package/src/lib/utils/escape-html.js +41 -0
  408. package/src/lib/utils/escape-html.js.map +1 -0
  409. package/src/lib/utils/generate-preset-id.d.ts +19 -0
  410. package/src/lib/utils/generate-preset-id.js +25 -0
  411. package/src/lib/utils/generate-preset-id.js.map +1 -0
  412. package/src/lib/utils/member-continue.d.ts +45 -0
  413. package/src/lib/utils/member-continue.js +49 -0
  414. package/src/lib/utils/member-continue.js.map +1 -0
  415. package/src/lib/utils/use-storefront-purchase-event.d.ts +60 -0
  416. package/src/lib/utils/use-storefront-purchase-event.js +142 -0
  417. package/src/lib/utils/use-storefront-purchase-event.js.map +1 -0
@@ -0,0 +1,1022 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
3
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
4
+ /**
5
+ * @license
6
+ * Copyright 2026 Aglyn LLC
7
+ *
8
+ * Licensed under the Apache License, Version 2.0 (the "License");
9
+ * you may not use this file except in compliance with the License.
10
+ * You may obtain a copy of the License at
11
+ *
12
+ * http://www.apache.org/licenses/LICENSE-2.0
13
+ *
14
+ * Unless required by applicable law or agreed to in writing, software
15
+ * distributed under the License is distributed on an "AS IS" BASIS,
16
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ * See the License for the specific language governing permissions and
18
+ * limitations under the License.
19
+ */ import * as Aglyn from "@aglyn/aglyn";
20
+ import { buildAddToCartParams, buildBeginCheckoutParams, trackEvent, trackEventBeforeNavigation } from "@aglyn/aglyn/app-utils/analytics-events";
21
+ import { isPaymentsNotConfigured, storefrontPaymentsNotConfiguredText } from "@aglyn/aglyn/app-utils/payments-configured";
22
+ import * as CommerceModel from "../model/index.js";
23
+ import { mdiTagOutline } from "@aglyn/shared-data-mdi";
24
+ import Alert from "@mui/material/Alert";
25
+ import Box from "@mui/material/Box";
26
+ import Button from "@mui/material/Button";
27
+ import Chip from "@mui/material/Chip";
28
+ import MenuItem from "@mui/material/MenuItem";
29
+ import Skeleton from "@mui/material/Skeleton";
30
+ import TextField from "@mui/material/TextField";
31
+ import ToggleButton from "@mui/material/ToggleButton";
32
+ import ToggleButtonGroup from "@mui/material/ToggleButtonGroup";
33
+ import Typography from "@mui/material/Typography";
34
+ import { Suspense, forwardRef, lazy, useEffect, useMemo, useRef, useState } from "react";
35
+ import { BUNDLE_ID } from "../constants/bundle-common.js";
36
+ import { generatePresetId } from "../utils/generate-preset-id.js";
37
+ import { useStorefrontPurchaseEvent } from "../utils/use-storefront-purchase-event.js";
38
+ import { CART_UPDATED_EVENT } from "./cart.js";
39
+ import { ID as PRODUCT_REVIEWS_ID } from "./product-reviews.js";
40
+ import { ID as RELATED_PRODUCTS_ID } from "./related-products.js";
41
+ import { readLocalWishlist, toggleWishlist } from "./wishlist.js";
42
+ import { StorefrontPaymentElementFallback } from "./storefront-payment-element-fallback.js";
43
+ /**
44
+ * The Payment Element (AGL-1944), behind a lazy boundary rather than a plain
45
+ * import. Stripe.js and its React wrapper are a large dependency, the flag is
46
+ * OFF, and a static import would put the whole SDK into the bundle of every
47
+ * product page on every published site to serve a code path no shopper reaches.
48
+ * Split, it is fetched by the shoppers who actually get the in-page form.
49
+ */ const StorefrontPaymentElement = /*#__PURE__*/ lazy(()=>import("./storefront-payment-element.js").then((module)=>({
50
+ default: module.StorefrontPaymentElement
51
+ })));
52
+ // Component ids are persisted in screen documents; never rename.
53
+ export const ID = 'product-detail';
54
+ const SAMPLE = {
55
+ id: 'sample',
56
+ name: 'Sample product',
57
+ slug: '#',
58
+ description: 'Drop this block on your product page template.',
59
+ mediaUrls: [],
60
+ options: [
61
+ {
62
+ name: 'Size',
63
+ values: [
64
+ 'S',
65
+ 'M',
66
+ 'L'
67
+ ]
68
+ }
69
+ ],
70
+ variants: [
71
+ {
72
+ id: 'a',
73
+ options: {
74
+ Size: 'S'
75
+ },
76
+ priceUsd: 29,
77
+ soldOut: false
78
+ },
79
+ {
80
+ id: 'b',
81
+ options: {
82
+ Size: 'M'
83
+ },
84
+ priceUsd: 29,
85
+ soldOut: false
86
+ },
87
+ {
88
+ id: 'c',
89
+ options: {
90
+ Size: 'L'
91
+ },
92
+ priceUsd: 32,
93
+ soldOut: true
94
+ }
95
+ ]
96
+ };
97
+ /**
98
+ * The GA4 `items` entry for one line of this product.
99
+ *
100
+ * `item_id` is the PRODUCT id and never the variant's, matching the
101
+ * `view_item` above and the cart's lines below: GA joins the funnel on that
102
+ * id, and a `begin_checkout` keyed on a variant would report a product nothing
103
+ * else on the storefront had ever mentioned.
104
+ *
105
+ * `price` is the resolved variant's, which arrived from the server's product
106
+ * payload — the same figure `checkout` prices the charge from, so the reported
107
+ * value and the amount Stripe collects come from one source.
108
+ */ function buyItem(product, variant, quantity) {
109
+ return {
110
+ item_id: product.id,
111
+ item_name: product.name,
112
+ price: variant == null ? void 0 : variant.priceUsd,
113
+ quantity
114
+ };
115
+ }
116
+ function slugFromLocation() {
117
+ if (typeof window === 'undefined') return '';
118
+ const match = window.location.pathname.match(/\/products\/([^/?#]+)/);
119
+ return match ? decodeURIComponent(match[1]) : '';
120
+ }
121
+ /**
122
+ * Product detail block (AGL-292): gallery, option pickers that resolve
123
+ * the variant (price/media/stock follow), quantity, and a buy button
124
+ * that charges through the server-priced checkout with the selected
125
+ * variant. Resolves its product from the /products/{slug} URL unless a
126
+ * slug prop pins it; sample data on the inert canvas.
127
+ */ const ProductDetail = /*#__PURE__*/ forwardRef((props, ref)=>{
128
+ var _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
129
+ var _site_pageData_commerce, _site_pageData;
130
+ const { slug: slugProp, buyLabel, hideDescription, showCoupon } = props, rest = _object_without_properties_loose(props, [
131
+ "slug",
132
+ "buyLabel",
133
+ "hideDescription",
134
+ "showCoupon"
135
+ ]);
136
+ // Node styles ride the renderer-merged sx; recompose (stack.ts pattern).
137
+ const nodeSx = Array.isArray(props['sx']) ? props['sx'] : [
138
+ props['sx']
139
+ ];
140
+ const site = Aglyn.useSite();
141
+ const siteFetch = Aglyn.useSiteFetch();
142
+ const { hostId } = site;
143
+ // The single-product ("buy now") path returns the shopper to this page
144
+ // rather than to the cart, so the PDP is the second of the two surfaces
145
+ // that has to be able to report `purchase` (AGL-1641). Both mount points
146
+ // share one guard, so a page carrying a cart AND a PDP still sends one.
147
+ useStorefrontPurchaseEvent(hostId, siteFetch);
148
+ // Seeded from the server-resolved page data (AGL-659) so the PDP renders
149
+ // its real content in the SSR HTML. Starting at null meant the server
150
+ // emitted a <Skeleton> and the crawler got a product page with no
151
+ // product in it. Absent in the besigner/preview, where the effect below
152
+ // still fetches — so this is an optimisation, not a new requirement.
153
+ const seededProduct = (_site_pageData = site.pageData) == null ? void 0 : (_site_pageData_commerce = _site_pageData.commerce) == null ? void 0 : _site_pageData_commerce.product;
154
+ const [detail, setDetail] = useState(seededProduct != null ? seededProduct : null);
155
+ const [selections, setSelections] = useState({});
156
+ const [quantity, setQuantity] = useState(1);
157
+ /** A discount or coupon code typed on the product page. */ const [coupon, setCoupon] = useState('');
158
+ const [activeImage, setActiveImage] = useState(0);
159
+ // `unconfigured` is not an `error` with softer words (AGL-2019). A store
160
+ // with no Stripe key answers 501, and rendering that at `severity="error"`
161
+ // tells a shopper their payment failed when nothing was ever attempted —
162
+ // the same distinction `ask` already makes, and the same one the cart's
163
+ // 423 lockdown branch makes. It is the terminal one: it latches Buy off,
164
+ // because every further click gets the identical refusal.
165
+ const [status, setStatus] = useState('idle');
166
+ const [message, setMessage] = useState('');
167
+ // Buy-now's half of AGL-1721: asked only when the server refuses to price
168
+ // shipping without a destination, so a digital product, a subscription, or
169
+ // a merchant whose rates are the same everywhere never shows it. `null` is
170
+ // "not asked" — the field appearing is the server's answer, not a guess.
171
+ const [shipTo, setShipTo] = useState('');
172
+ const [shipCountries, setShipCountries] = useState(null);
173
+ const [added, setAdded] = useState(false);
174
+ const [wishlisted, setWishlisted] = useState(false);
175
+ const [notifyEmail, setNotifyEmail] = useState('');
176
+ const [notifyState, setNotifyState] = useState('idle');
177
+ // Buyer-chosen billing (AGL-545): only meaningful when the product
178
+ // is subscriptionOptional; defaults to a one-time purchase.
179
+ const [billing, setBilling] = useState('once');
180
+ /**
181
+ * The in-page checkout session (AGL-1944), null on every store until the
182
+ * flag AND a publishable key say otherwise. A `clientSecret` is Stripe's
183
+ * instruction to the browser; holding it says nothing about money having
184
+ * moved, and nothing in this component ever claims it has.
185
+ */ const [nativeCheckout, setNativeCheckout] = useState(null);
186
+ const slug = slugProp || slugFromLocation();
187
+ useEffect(()=>{
188
+ if (hostId && resolvedId) {
189
+ setWishlisted(readLocalWishlist(hostId).includes(resolvedId));
190
+ }
191
+ // eslint-disable-next-line react-hooks/exhaustive-deps
192
+ }, [
193
+ hostId,
194
+ detail
195
+ ]);
196
+ useEffect(()=>{
197
+ if (!hostId || !slug) return;
198
+ // Already delivered with the page (AGL-659) — refetching the identical
199
+ // payload on hydrate would just be a wasted round trip per visitor.
200
+ if (seededProduct && seededProduct.slug === slug) return;
201
+ let active = true;
202
+ void fetch(`/api/commerce/product?hostId=${encodeURIComponent(hostId)}` + `&slug=${encodeURIComponent(slug)}`).then((response)=>response.ok ? response.json() : null).then((payload)=>{
203
+ if (!active) return;
204
+ const product = payload == null ? void 0 : payload.product;
205
+ setDetail(product != null ? product : 'missing');
206
+ if (product) {
207
+ var _product_variants_find, _ref;
208
+ // GA4 ecommerce mirror (AGL-327), through the shared taxonomy
209
+ // since AGL-1591 rather than raw gtag — same consent gate, same
210
+ // sanitizer, and the name is now checked by the compiler.
211
+ trackEvent('view_item', {
212
+ items: [
213
+ {
214
+ item_id: product.id,
215
+ item_name: product.name
216
+ }
217
+ ]
218
+ });
219
+ const first = (_product_variants_find = product.variants.find((variant)=>!variant.soldOut)) != null ? _product_variants_find : product.variants[0];
220
+ setSelections((_ref = first == null ? void 0 : first.options) != null ? _ref : {});
221
+ }
222
+ }).catch(()=>{
223
+ if (active) setDetail('missing');
224
+ });
225
+ return ()=>{
226
+ active = false;
227
+ };
228
+ }, [
229
+ hostId,
230
+ slug
231
+ ]);
232
+ const resolvedId = hostId && detail && detail !== 'missing' ? detail.id : null;
233
+ const resolved = hostId ? detail === 'missing' ? null : detail : SAMPLE;
234
+ const variant = useMemo(()=>{
235
+ var _CommerceModel_findVariant;
236
+ if (!resolved) return undefined;
237
+ return (_CommerceModel_findVariant = CommerceModel.findVariant({
238
+ variants: resolved.variants
239
+ }, selections)) != null ? _CommerceModel_findVariant : resolved.variants[0];
240
+ }, [
241
+ resolved,
242
+ selections
243
+ ]);
244
+ // Add to cart (AGL-293) beside instant buy; badge refresh via event.
245
+ const handleAddToCart = async ()=>{
246
+ if (!hostId || !resolved || !variant) return;
247
+ setAdded(false);
248
+ const response = await siteFetch('/api/commerce/cart', {
249
+ method: 'POST',
250
+ headers: {
251
+ 'Content-Type': 'application/json'
252
+ },
253
+ body: JSON.stringify({
254
+ hostId,
255
+ action: 'add',
256
+ productId: resolved.id,
257
+ variantId: variant.id,
258
+ quantity
259
+ })
260
+ }).catch(()=>null);
261
+ if (response == null ? void 0 : response.ok) {
262
+ setAdded(true);
263
+ // Priced (AGL-1591's shape, completed): the resolved variant's price
264
+ // and the chosen quantity are both known here and both come from the
265
+ // server's product payload, so GA4's "value added to cart" is a real
266
+ // number rather than the empty column an items-only hit leaves. The
267
+ // `value` describes what was JUST ADDED, not the cart's new total —
268
+ // see `buildAddToCartParams`.
269
+ trackEvent('add_to_cart', buildAddToCartParams({
270
+ items: [
271
+ buyItem(resolved, variant, quantity)
272
+ ]
273
+ }));
274
+ window.dispatchEvent(new Event(CART_UPDATED_EVENT));
275
+ }
276
+ };
277
+ /**
278
+ * Idempotency key for ONE buy-now attempt (AGL-1697).
279
+ *
280
+ * Minted lazily on the first buy click, retired whenever the purchase
281
+ * changes shape — a different product, variant, quantity, billing choice
282
+ * or destination is a different attempt. A retry of THIS attempt presents
283
+ * the same key, so the server replays the original session instead of
284
+ * opening a second one (for a subscription product, a second RECURRING
285
+ * subscription).
286
+ */ const attemptKey = useRef('');
287
+ useEffect(()=>{
288
+ attemptKey.current = '';
289
+ // `coupon` is in here because it CHANGES THE PRICE. Without it a shopper
290
+ // who buys, comes back, types a code and buys again presents the same
291
+ // key, and the server replays the original full-price session — a quoted
292
+ // number that is not the number charged, which is the whole defect class
293
+ // this path has been cleared of.
294
+ }, [
295
+ resolved == null ? void 0 : resolved.id,
296
+ variant == null ? void 0 : variant.id,
297
+ quantity,
298
+ billing,
299
+ shipTo,
300
+ coupon
301
+ ]);
302
+ const handleBuy = async ()=>{
303
+ if (!hostId || !resolved || !variant || status === 'sending') return;
304
+ setStatus('sending');
305
+ setMessage('');
306
+ if (!attemptKey.current) {
307
+ var _ref;
308
+ var _globalThis_crypto_randomUUID, _globalThis_crypto;
309
+ attemptKey.current = (_ref = (_globalThis_crypto = globalThis.crypto) == null ? void 0 : (_globalThis_crypto_randomUUID = _globalThis_crypto.randomUUID) == null ? void 0 : _globalThis_crypto_randomUUID.call(_globalThis_crypto)) != null ? _ref : `${Date.now()}-${Math.random().toString(36).slice(2)}`;
310
+ }
311
+ try {
312
+ var _ref1;
313
+ const response = await siteFetch('/api/commerce/checkout', {
314
+ method: 'POST',
315
+ headers: {
316
+ 'Content-Type': 'application/json',
317
+ 'Idempotency-Key': attemptKey.current
318
+ },
319
+ body: JSON.stringify(_extends({
320
+ hostId,
321
+ productId: resolved.id,
322
+ variantId: variant.id,
323
+ quantity
324
+ }, resolved.subscriptionOptional ? {
325
+ billing
326
+ } : {}, shipTo ? {
327
+ shippingCountry: shipTo
328
+ } : {}, coupon.trim() ? {
329
+ couponCode: coupon.trim()
330
+ } : {}))
331
+ });
332
+ const payload = await response.json().catch(()=>({}));
333
+ // In-page payment (AGL-1944). A native session returns a client secret
334
+ // and NO url — the two are mutually exclusive by construction, so the
335
+ // redirect branch below is unreachable in native mode and vice versa.
336
+ // Checked FIRST so a server that somehow sent both cannot silently
337
+ // navigate the shopper away from the form we just decided to show.
338
+ if (response.ok && (payload == null ? void 0 : payload.clientSecret) && (payload == null ? void 0 : payload.publishableKey)) {
339
+ // Buy-now's `begin_checkout`. The cart path has reported this since
340
+ // AGL-1591 and this one never did, so a storefront whose shoppers
341
+ // skip the cart showed `view_item` → `add_to_cart` → nothing →
342
+ // `purchase`: GA4's shopping funnel put every single-product sale in
343
+ // the "abandoned checkout" bucket, and the merchant's checkout rate
344
+ // read as a collapse rather than as an unmeasured path.
345
+ //
346
+ // Reported on BOTH branches, and from the same place, for the reason
347
+ // the cart states: a count that halved the day the in-page payment
348
+ // flag flipped would look like a conversion collapse.
349
+ trackEvent('begin_checkout', buildBeginCheckoutParams({
350
+ items: [
351
+ buyItem(resolved, variant, quantity)
352
+ ]
353
+ }));
354
+ setNativeCheckout({
355
+ clientSecret: String(payload.clientSecret),
356
+ publishableKey: String(payload.publishableKey)
357
+ });
358
+ setStatus('idle');
359
+ return;
360
+ }
361
+ if (response.ok && (payload == null ? void 0 : payload.url)) {
362
+ // Awaited before the redirect (AGL-1580), for the reason spelled out
363
+ // on the cart's matching branch: delivery here is a synchronous
364
+ // `window.gtag` call today and the await costs nothing, but the
365
+ // property that makes a bare call safe is invisible from this file.
366
+ await trackEventBeforeNavigation('begin_checkout', buildBeginCheckoutParams({
367
+ items: [
368
+ buyItem(resolved, variant, quantity)
369
+ ]
370
+ }));
371
+ window.location.assign(payload.url);
372
+ return;
373
+ }
374
+ // Buy-now's half of AGL-2019. The server's own 501 wording is not
375
+ // rendered to a visitor; this surface is public.
376
+ if (isPaymentsNotConfigured(response.status)) {
377
+ setMessage(storefrontPaymentsNotConfiguredText());
378
+ setStatus('unconfigured');
379
+ return;
380
+ }
381
+ if (payload == null ? void 0 : payload.needsShippingCountry) {
382
+ var _ref2;
383
+ var _payload_shippingCountries;
384
+ setShipCountries(((_payload_shippingCountries = payload.shippingCountries) == null ? void 0 : _payload_shippingCountries.length) ? payload.shippingCountries : [
385
+ ...CommerceModel.CHECKOUT_SHIPPING_COUNTRIES
386
+ ]);
387
+ setMessage(String((_ref2 = payload == null ? void 0 : payload.error) != null ? _ref2 : ''));
388
+ // An unserved destination is a refusal and reads as one; being
389
+ // asked the first time is not.
390
+ setStatus(shipTo ? 'error' : 'ask');
391
+ return;
392
+ }
393
+ setMessage(String((_ref1 = payload == null ? void 0 : payload.error) != null ? _ref1 : ''));
394
+ setStatus('error');
395
+ } catch (unused) {
396
+ setStatus('error');
397
+ }
398
+ };
399
+ if (hostId && detail === null) {
400
+ return /*#__PURE__*/ _jsxs(Box, _extends({
401
+ ref: ref
402
+ }, rest, {
403
+ sx: [
404
+ {
405
+ display: 'flex',
406
+ gap: 3
407
+ },
408
+ ...nodeSx
409
+ ],
410
+ children: [
411
+ /*#__PURE__*/ _jsx(Skeleton, {
412
+ variant: "rectangular",
413
+ width: 320,
414
+ height: 320
415
+ }),
416
+ /*#__PURE__*/ _jsxs(Box, {
417
+ sx: {
418
+ flex: 1
419
+ },
420
+ children: [
421
+ /*#__PURE__*/ _jsx(Skeleton, {
422
+ width: "60%",
423
+ height: 36
424
+ }),
425
+ /*#__PURE__*/ _jsx(Skeleton, {
426
+ width: "25%"
427
+ }),
428
+ /*#__PURE__*/ _jsx(Skeleton, {
429
+ width: "90%"
430
+ })
431
+ ]
432
+ })
433
+ ]
434
+ }));
435
+ }
436
+ if (!resolved) {
437
+ return /*#__PURE__*/ _jsx(Box, _extends({
438
+ ref: ref
439
+ }, rest, {
440
+ sx: [
441
+ {
442
+ p: 3
443
+ },
444
+ ...nodeSx
445
+ ],
446
+ children: /*#__PURE__*/ _jsx(Typography, {
447
+ variant: "body2",
448
+ color: "text.secondary",
449
+ children: 'Product not found.'
450
+ })
451
+ }));
452
+ }
453
+ // Every rendered `<img src>` on this page goes through
454
+ // `siteRelativeMediaSrc` (AGL-1726). Commerce called NO resolver at all,
455
+ // which cost it two things at once: a `media:` reference — writable via
456
+ // the resources API and the CSV importer — would have reached an `<img>`
457
+ // as the literal string, and a stored absolute
458
+ // `https://{subdomain}.aglyn.app/api/media/cdn/…` stayed absolute, so a
459
+ // white-label storefront on the customer's own domain served product
460
+ // photos naming OUR platform, cross-origin, in page source and in every
461
+ // visitor's request. Production carried exactly one such document; the
462
+ // resolver fixes it at READ time, so no backfill stands between the
463
+ // defect and the fix.
464
+ //
465
+ // Deliberately NOT applied to `resolved.mediaUrls` wholesale: the
466
+ // schema.org `image` array below is read out of band by a crawler, where
467
+ // an absolute URL is the point. That one wants `absoluteMediaSrc` with
468
+ // the site's own origin, which is the tenant page's job (AGL-1725).
469
+ const galleryImage = Aglyn.siteRelativeMediaSrc((_ref = (_ref1 = variant == null ? void 0 : variant.imageUrl) != null ? _ref1 : resolved.mediaUrls[activeImage]) != null ? _ref : resolved.mediaUrls[0], {
470
+ hostId
471
+ });
472
+ // Subscription framing (AGL-545): subscription-only products price as
473
+ // $X/mo|/yr with a "Subscribe" button; subscriptionOptional products
474
+ // surface the one-time/subscribe toggle instead. Same price either way
475
+ // — the server re-prices from the product doc regardless.
476
+ const subscription = resolved.subscription;
477
+ const intervalSuffix = (subscription == null ? void 0 : subscription.interval) === 'year' ? '/yr' : '/mo';
478
+ const subscribing = Boolean(subscription) && (!resolved.subscriptionOptional || billing === 'subscribe');
479
+ // schema.org Product/Offer (AGL-299). Kept ONLY for the case where this
480
+ // block renders without server-seeded page data — the besigner preview,
481
+ // or a page whose resolver didn't supply it. When the tenant page seeds
482
+ // us it emits the same Product node server-side (AGL-660), and two
483
+ // Product nodes for one item is worse than one, so we stand down.
484
+ const structuredData = hostId && resolvedId && !seededProduct ? _extends({
485
+ '@context': 'https://schema.org',
486
+ '@type': 'Product',
487
+ name: resolved.name
488
+ }, resolved.description ? {
489
+ description: resolved.description
490
+ } : {}, resolved.mediaUrls.length ? {
491
+ image: resolved.mediaUrls
492
+ } : {}, {
493
+ offers: {
494
+ '@type': 'Offer',
495
+ priceCurrency: 'USD',
496
+ price: String((_ref2 = variant == null ? void 0 : variant.priceUsd) != null ? _ref2 : 0),
497
+ availability: (variant == null ? void 0 : variant.soldOut) ? 'https://schema.org/OutOfStock' : 'https://schema.org/InStock'
498
+ }
499
+ }) : null;
500
+ return /*#__PURE__*/ _jsxs(Box, _extends({
501
+ ref: ref
502
+ }, rest, {
503
+ sx: [
504
+ {
505
+ display: 'flex',
506
+ gap: 3,
507
+ flexDirection: {
508
+ xs: 'column',
509
+ md: 'row'
510
+ }
511
+ },
512
+ ...nodeSx
513
+ ],
514
+ children: [
515
+ /*#__PURE__*/ _jsxs(Box, {
516
+ sx: {
517
+ flex: 1,
518
+ minWidth: 0
519
+ },
520
+ children: [
521
+ galleryImage ? /*#__PURE__*/ _jsx(Box, {
522
+ component: "img",
523
+ src: galleryImage,
524
+ alt: resolved.name,
525
+ // DELIBERATELY NOT DEFERRED (AGL-2486). This is the gallery
526
+ // hero at the top of a product page — the one image on this
527
+ // surface that really is the LCP candidate, and the browser
528
+ // default here is already `eager`. Spreading
529
+ // `DEFERRED_IMAGE_ATTRIBUTES` over it to "finish the job" is
530
+ // the obvious next edit and it re-introduces the bug this
531
+ // issue opened with: an LCP image not discovered until after
532
+ // layout has run. The thumbnail strip below it IS deferred.
533
+ //
534
+ // No `fetchpriority` either, for the reason written out at
535
+ // `image.tsx`: `high` is a claim about every other request in
536
+ // flight, and a page whose real LCP is the product NAME would
537
+ // pay for that claim.
538
+ sx: {
539
+ width: '100%',
540
+ aspectRatio: '1 / 1',
541
+ objectFit: 'cover',
542
+ borderRadius: 1
543
+ }
544
+ }) : /*#__PURE__*/ _jsx(Box, {
545
+ sx: {
546
+ width: '100%',
547
+ aspectRatio: '1 / 1',
548
+ bgcolor: 'action.hover',
549
+ borderRadius: 1
550
+ }
551
+ }),
552
+ resolved.mediaUrls.length > 1 ? /*#__PURE__*/ _jsx(Box, {
553
+ sx: {
554
+ display: 'flex',
555
+ gap: 1,
556
+ mt: 1,
557
+ flexWrap: 'wrap'
558
+ },
559
+ children: resolved.mediaUrls.map((url, index)=>/*#__PURE__*/ _jsx(Box, _extends({
560
+ component: "img",
561
+ // Same resolver as the hero (AGL-1726) — a thumbnail is an
562
+ // `<img>` on the customer's page and leaks exactly as much.
563
+ src: Aglyn.siteRelativeMediaSrc(url, {
564
+ hostId
565
+ }),
566
+ alt: "",
567
+ onClick: ()=>setActiveImage(index),
568
+ sx: {
569
+ width: 56,
570
+ height: 56,
571
+ objectFit: 'cover',
572
+ borderRadius: 1,
573
+ cursor: 'pointer',
574
+ border: 2,
575
+ borderColor: index === activeImage ? 'primary.main' : 'transparent'
576
+ }
577
+ }, Aglyn.DEFERRED_IMAGE_ATTRIBUTES), `${url}-${index}`))
578
+ }) : null
579
+ ]
580
+ }),
581
+ structuredData ? /*#__PURE__*/ _jsx("script", {
582
+ type: "application/ld+json",
583
+ dangerouslySetInnerHTML: {
584
+ __html: Aglyn.safeJsonLd(structuredData)
585
+ }
586
+ }) : null,
587
+ /*#__PURE__*/ _jsxs(Box, {
588
+ sx: {
589
+ flex: 1,
590
+ minWidth: 0
591
+ },
592
+ children: [
593
+ /*#__PURE__*/ _jsx(Typography, {
594
+ variant: "h4",
595
+ component: "h1",
596
+ gutterBottom: true,
597
+ children: resolved.name
598
+ }),
599
+ /*#__PURE__*/ _jsxs(Box, {
600
+ sx: {
601
+ display: 'flex',
602
+ gap: 1,
603
+ alignItems: 'center',
604
+ mb: 2
605
+ },
606
+ children: [
607
+ /*#__PURE__*/ _jsx(Typography, {
608
+ variant: "h6",
609
+ children: `$${(_ref3 = variant == null ? void 0 : variant.priceUsd) != null ? _ref3 : 0}${subscribing ? intervalSuffix : ''}`
610
+ }),
611
+ subscribing && (subscription == null ? void 0 : subscription.trialDays) ? /*#__PURE__*/ _jsx(Typography, {
612
+ variant: "caption",
613
+ color: "text.secondary",
614
+ children: `${subscription.trialDays}-day free trial`
615
+ }) : null,
616
+ (variant == null ? void 0 : variant.compareAtPriceUsd) ? /*#__PURE__*/ _jsxs(_Fragment, {
617
+ children: [
618
+ /*#__PURE__*/ _jsx(Typography, {
619
+ variant: "body1",
620
+ color: "text.disabled",
621
+ sx: {
622
+ textDecoration: 'line-through'
623
+ },
624
+ children: `$${variant.compareAtPriceUsd}`
625
+ }),
626
+ /*#__PURE__*/ _jsx(Chip, {
627
+ label: "Sale",
628
+ size: "small",
629
+ color: "primary"
630
+ })
631
+ ]
632
+ }) : null,
633
+ (variant == null ? void 0 : variant.soldOut) ? /*#__PURE__*/ _jsx(Chip, {
634
+ label: "Sold out",
635
+ size: "small",
636
+ variant: "outlined"
637
+ }) : null,
638
+ /*#__PURE__*/ _jsx(Button, {
639
+ size: "small",
640
+ onClick: async ()=>{
641
+ if (hostId && resolved.id !== 'sample') {
642
+ setWishlisted(await toggleWishlist(hostId, resolved.id, siteFetch));
643
+ }
644
+ },
645
+ children: wishlisted ? '♥ Saved' : '♡ Save'
646
+ })
647
+ ]
648
+ }),
649
+ subscription && resolved.subscriptionOptional ? /*#__PURE__*/ _jsxs(ToggleButtonGroup, {
650
+ value: billing,
651
+ exclusive: true,
652
+ size: "small",
653
+ onChange: (_event, value)=>{
654
+ if (value === 'once' || value === 'subscribe') {
655
+ setBilling(value);
656
+ }
657
+ },
658
+ sx: {
659
+ mb: 2
660
+ },
661
+ children: [
662
+ /*#__PURE__*/ _jsx(ToggleButton, {
663
+ value: "once",
664
+ children: `One-time $${(_ref4 = variant == null ? void 0 : variant.priceUsd) != null ? _ref4 : 0}`
665
+ }),
666
+ /*#__PURE__*/ _jsx(ToggleButton, {
667
+ value: "subscribe",
668
+ children: `Subscribe $${(_ref5 = variant == null ? void 0 : variant.priceUsd) != null ? _ref5 : 0}${intervalSuffix}`
669
+ })
670
+ ]
671
+ }) : null,
672
+ resolved.options.map((option)=>{
673
+ var _selections_option_name;
674
+ return /*#__PURE__*/ _jsx(TextField, {
675
+ label: option.name,
676
+ value: (_selections_option_name = selections[option.name]) != null ? _selections_option_name : '',
677
+ onChange: (event)=>setSelections((prev)=>_extends({}, prev, {
678
+ [option.name]: event.target.value
679
+ })),
680
+ size: "small",
681
+ select: true,
682
+ fullWidth: true,
683
+ sx: {
684
+ mb: 1.5
685
+ },
686
+ children: option.values.map((value)=>/*#__PURE__*/ _jsx(MenuItem, {
687
+ value: value,
688
+ children: value
689
+ }, value))
690
+ }, option.name);
691
+ }),
692
+ showCoupon ? /*#__PURE__*/ _jsx(TextField, {
693
+ label: "Discount code",
694
+ value: coupon,
695
+ onChange: (event)=>setCoupon(event.target.value),
696
+ size: "small",
697
+ sx: {
698
+ mb: 2,
699
+ display: 'block'
700
+ }
701
+ }) : null,
702
+ /*#__PURE__*/ _jsxs(Box, {
703
+ sx: {
704
+ display: 'flex',
705
+ gap: 1.5,
706
+ alignItems: 'center',
707
+ mb: 2
708
+ },
709
+ children: [
710
+ /*#__PURE__*/ _jsx(TextField, {
711
+ label: "Qty",
712
+ value: quantity,
713
+ onChange: (event)=>setQuantity(Math.max(1, Math.min(99, Math.round(Number(event.target.value)) || 1))),
714
+ size: "small",
715
+ sx: {
716
+ width: 80
717
+ },
718
+ slotProps: {
719
+ htmlInput: {
720
+ inputMode: 'numeric'
721
+ }
722
+ }
723
+ }),
724
+ /*#__PURE__*/ _jsx(Button, {
725
+ variant: "outlined",
726
+ color: "primary",
727
+ size: "large",
728
+ disabled: !hostId || (variant == null ? void 0 : variant.soldOut),
729
+ onClick: handleAddToCart,
730
+ children: added ? 'Added ✓' : 'Add to cart'
731
+ }),
732
+ /*#__PURE__*/ _jsx(Button, {
733
+ variant: "contained",
734
+ color: "primary",
735
+ size: "large",
736
+ disabled: !hostId || status === 'sending' || (variant == null ? void 0 : variant.soldOut) || // No payments on this deployment: the same 501 every time, so
737
+ // the control latches off rather than inviting a retry that
738
+ // cannot succeed (AGL-2019).
739
+ status === 'unconfigured' || // Asked but unanswered: the server would only refuse again.
740
+ shipCountries !== null && !shipTo,
741
+ onClick: handleBuy,
742
+ sx: {
743
+ flex: 1
744
+ },
745
+ children: (variant == null ? void 0 : variant.soldOut) ? 'Sold out' : status === 'sending' ? // it is the shopper's only clue about what is about to
746
+ // happen to their page (AGL-1944).
747
+ nativeCheckout ? 'Opening…' : 'Redirecting…' : buyLabel || (subscribing ? 'Subscribe' : 'Buy now')
748
+ })
749
+ ]
750
+ }),
751
+ nativeCheckout ? /*#__PURE__*/ _jsx(Suspense, {
752
+ fallback: /*#__PURE__*/ _jsx(StorefrontPaymentElementFallback, {}),
753
+ children: /*#__PURE__*/ _jsx(StorefrontPaymentElement, {
754
+ clientSecret: nativeCheckout.clientSecret,
755
+ publishableKey: nativeCheckout.publishableKey,
756
+ payLabel: buyLabel || (subscribing ? 'Subscribe' : 'Pay now'),
757
+ // Cancelling drops the form and leaves the session open —
758
+ // deliberately. The shopper may come back to the same
759
+ // attempt key, and an abandoned session is what the AGL-323
760
+ // recovery emails are built on. Nothing is expired from the
761
+ // browser: that is a write against the merchant's account.
762
+ onCancel: ()=>setNativeCheckout(null)
763
+ })
764
+ }) : null,
765
+ shipCountries ? /*#__PURE__*/ _jsx(TextField, {
766
+ select: true,
767
+ label: "Ship to",
768
+ value: shipTo,
769
+ onChange: (event)=>setShipTo(event.target.value),
770
+ size: "small",
771
+ fullWidth: true,
772
+ helperText: "Shipping rates depend on where this is going",
773
+ sx: {
774
+ mb: 2
775
+ },
776
+ children: shipCountries.map((code)=>{
777
+ var _CommerceModel_CHECKOUT_SHIPPING_COUNTRY_NAMES_code;
778
+ return /*#__PURE__*/ _jsx(MenuItem, {
779
+ value: code,
780
+ children: (_CommerceModel_CHECKOUT_SHIPPING_COUNTRY_NAMES_code = CommerceModel.CHECKOUT_SHIPPING_COUNTRY_NAMES[code]) != null ? _CommerceModel_CHECKOUT_SHIPPING_COUNTRY_NAMES_code : code
781
+ }, code);
782
+ })
783
+ }) : null,
784
+ status === 'ask' || status === 'unconfigured' ? /*#__PURE__*/ _jsx(Alert, {
785
+ severity: "info",
786
+ sx: {
787
+ mb: 2
788
+ },
789
+ children: message
790
+ }) : null,
791
+ status === 'error' ? /*#__PURE__*/ _jsx(Alert, {
792
+ severity: "error",
793
+ sx: {
794
+ mb: 2
795
+ },
796
+ children: message || 'Checkout is unavailable right now.'
797
+ }) : null,
798
+ (variant == null ? void 0 : variant.soldOut) && hostId ? notifyState === 'done' ? /*#__PURE__*/ _jsx(Alert, {
799
+ severity: "success",
800
+ sx: {
801
+ mb: 2
802
+ },
803
+ children: 'We will email you when it is back.'
804
+ }) : /*#__PURE__*/ _jsxs(Box, {
805
+ sx: {
806
+ display: 'flex',
807
+ gap: 1,
808
+ mb: 2
809
+ },
810
+ children: [
811
+ /*#__PURE__*/ _jsx(TextField, {
812
+ placeholder: "you@example.com",
813
+ type: "email",
814
+ // Third instance of the nameless-input defect (AGL-2392).
815
+ // Named for its job rather than "Email address": this row
816
+ // appears inside a product page that may also carry the
817
+ // newsletter block, and two fields both announced as
818
+ // "Email address" is barely better than none.
819
+ slotProps: {
820
+ htmlInput: {
821
+ 'aria-label': 'Email address for back-in-stock alert'
822
+ }
823
+ },
824
+ value: notifyEmail,
825
+ onChange: (event)=>setNotifyEmail(event.target.value),
826
+ size: "small",
827
+ sx: {
828
+ flex: 1
829
+ }
830
+ }),
831
+ /*#__PURE__*/ _jsx(Button, {
832
+ size: "small",
833
+ variant: "outlined",
834
+ disabled: !notifyEmail.trim(),
835
+ onClick: async ()=>{
836
+ const response = await siteFetch('/api/commerce/notify-restock', {
837
+ method: 'POST',
838
+ headers: {
839
+ 'Content-Type': 'application/json'
840
+ },
841
+ body: JSON.stringify({
842
+ hostId,
843
+ productId: resolved.id,
844
+ email: notifyEmail
845
+ })
846
+ }).catch(()=>null);
847
+ if (response == null ? void 0 : response.ok) setNotifyState('done');
848
+ },
849
+ children: 'Notify me'
850
+ })
851
+ ]
852
+ }) : null,
853
+ !hideDescription && resolved.description ? /*#__PURE__*/ _jsx(Typography, {
854
+ variant: "body1",
855
+ color: "text.secondary",
856
+ children: resolved.description
857
+ }) : null
858
+ ]
859
+ })
860
+ ]
861
+ }));
862
+ });
863
+ ProductDetail.displayName = 'AglynProductDetail';
864
+ export const schema = {
865
+ $id: ID,
866
+ pluginId: BUNDLE_ID,
867
+ displayName: 'Product detail',
868
+ description: "One product's gallery, options and buy button.",
869
+ category: Aglyn.ComponentCategory.COMMERCE,
870
+ icon: {
871
+ path: mdiTagOutline.path,
872
+ sx: {
873
+ color: '#2e7d32'
874
+ }
875
+ },
876
+ flags: {
877
+ selfClosing: Aglyn.FEATURE_FLAG.ENABLED
878
+ },
879
+ attributes: [
880
+ {
881
+ name: 'slug',
882
+ label: 'Product slug',
883
+ description: 'Pin to one product; blank follows the /products/{slug} URL ' + '(product page template).',
884
+ component: Aglyn.FieldComponentType.TEXT_FIELD
885
+ },
886
+ {
887
+ name: 'buyLabel',
888
+ label: 'Buy button label',
889
+ description: 'Defaults to "Buy now".',
890
+ component: Aglyn.FieldComponentType.TEXT_FIELD
891
+ },
892
+ {
893
+ name: 'hideDescription',
894
+ label: 'Hide description',
895
+ description: 'Design the description separately with tokens.',
896
+ component: Aglyn.FieldComponentType.CHECKBOX
897
+ },
898
+ {
899
+ // Off by default, so no existing page changes shape on deploy. The cart
900
+ // has carried this field all along and the product page had none, so a
901
+ // shopper buying the same goods through Buy now had nowhere to enter a
902
+ // code the merchant had advertised.
903
+ name: 'showCoupon',
904
+ label: 'Show discount code field',
905
+ description: 'Lets a buyer enter a discount or coupon code before buying.',
906
+ component: Aglyn.FieldComponentType.CHECKBOX
907
+ }
908
+ ]
909
+ };
910
+ export const presets = [
911
+ {
912
+ $id: generatePresetId(ID),
913
+ type: Aglyn.NodeType.PRESET,
914
+ displayName: 'Product detail',
915
+ pluginId: BUNDLE_ID,
916
+ description: 'Gallery, variant picker, and buy button for one product',
917
+ category: Aglyn.ComponentCategory.COMMERCE,
918
+ icon: {
919
+ path: mdiTagOutline.path,
920
+ sx: {
921
+ color: '#2e7d32'
922
+ }
923
+ },
924
+ data: {
925
+ $id: null,
926
+ componentId: ID,
927
+ pluginId: BUNDLE_ID,
928
+ props: {}
929
+ }
930
+ },
931
+ {
932
+ // Product page (AGL-561): the commerce-standard PDP subtree —
933
+ // breadcrumb, detail, related products, reviews — for the product
934
+ // page template screen. `{{product.name}}` resolves there via the
935
+ // site page resolver's token pass (AGL-292); node shapes follow
936
+ // the Sections & Blocks convention (AGL-539) and reference only
937
+ // persisted component ids.
938
+ $id: generatePresetId(ID, 'page'),
939
+ type: Aglyn.NodeType.PRESET,
940
+ displayName: 'Product page',
941
+ pluginId: BUNDLE_ID,
942
+ description: 'Breadcrumb, product detail, related products, and reviews',
943
+ category: Aglyn.ComponentCategory.COMMERCE,
944
+ icon: {
945
+ path: mdiTagOutline.path,
946
+ sx: {
947
+ color: '#2e7d32'
948
+ }
949
+ },
950
+ data: {
951
+ $id: null,
952
+ componentId: 'muiStack',
953
+ pluginId: Aglyn.MUI_BUNDLE_ID,
954
+ props: {
955
+ spacing: 4
956
+ },
957
+ // Styling on the node's own sx, never in props (AGL-1346): both
958
+ // records render, but only `node.sx` is the one the Styles panel can
959
+ // read, edit or clear.
960
+ sx: {
961
+ paddingTop: 2,
962
+ paddingBottom: 2
963
+ },
964
+ nodes: [
965
+ {
966
+ $id: null,
967
+ componentId: 'muiStack',
968
+ pluginId: Aglyn.MUI_BUNDLE_ID,
969
+ props: {
970
+ direction: 'row',
971
+ spacing: 1
972
+ },
973
+ sx: {
974
+ alignItems: 'center'
975
+ },
976
+ nodes: [
977
+ {
978
+ $id: null,
979
+ componentId: 'muiScreenLink',
980
+ pluginId: Aglyn.MUI_BUNDLE_ID,
981
+ props: {
982
+ children: 'Shop',
983
+ size: 'small',
984
+ color: 'inherit'
985
+ }
986
+ },
987
+ {
988
+ $id: null,
989
+ componentId: 'muiTypography',
990
+ pluginId: Aglyn.MUI_BUNDLE_ID,
991
+ props: {
992
+ variant: 'body2',
993
+ children: '/ {{product.name}}'
994
+ }
995
+ }
996
+ ]
997
+ },
998
+ {
999
+ $id: null,
1000
+ componentId: ID,
1001
+ pluginId: BUNDLE_ID,
1002
+ props: {}
1003
+ },
1004
+ {
1005
+ $id: null,
1006
+ componentId: RELATED_PRODUCTS_ID,
1007
+ pluginId: BUNDLE_ID,
1008
+ props: {}
1009
+ },
1010
+ {
1011
+ $id: null,
1012
+ componentId: PRODUCT_REVIEWS_ID,
1013
+ pluginId: BUNDLE_ID,
1014
+ props: {}
1015
+ }
1016
+ ]
1017
+ }
1018
+ }
1019
+ ];
1020
+ export default ProductDetail;
1021
+
1022
+ //# sourceMappingURL=product-detail.js.map