@mohasinac/appkit 4.59.0 → 4.60.1

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 (532) hide show
  1. package/dist/.build-stamp.json +3 -3
  2. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +62 -5
  3. package/dist/_internal/client/features/maintenance/views/MaintenanceDashboardView.js +2 -2
  4. package/dist/_internal/server/features/brands/actions.js +78 -4
  5. package/dist/_internal/server/features/checkout/actions.d.ts +36 -13
  6. package/dist/_internal/server/features/checkout/actions.js +668 -183
  7. package/dist/_internal/server/features/checkout/supplier-identity.js +18 -1
  8. package/dist/_internal/server/features/gateway-events/index.d.ts +10 -0
  9. package/dist/_internal/server/features/gateway-events/index.js +10 -0
  10. package/dist/_internal/server/features/gateway-events/ingest.d.ts +127 -0
  11. package/dist/_internal/server/features/gateway-events/ingest.js +188 -0
  12. package/dist/_internal/server/features/gateway-events/redact.d.ts +66 -0
  13. package/dist/_internal/server/features/gateway-events/redact.js +151 -0
  14. package/dist/_internal/server/features/grievance/actions.d.ts +63 -0
  15. package/dist/_internal/server/features/grievance/actions.js +173 -0
  16. package/dist/_internal/server/features/grievance/index.d.ts +8 -0
  17. package/dist/_internal/server/features/grievance/index.js +8 -0
  18. package/dist/_internal/server/features/grouped/data.js +28 -3
  19. package/dist/_internal/server/features/lottery/actions.js +99 -4
  20. package/dist/_internal/server/features/order-completion/actions.d.ts +92 -0
  21. package/dist/_internal/server/features/order-completion/actions.js +336 -0
  22. package/dist/_internal/server/features/order-completion/index.d.ts +7 -0
  23. package/dist/_internal/server/features/order-completion/index.js +7 -0
  24. package/dist/_internal/server/features/orders/actions.d.ts +13 -0
  25. package/dist/_internal/server/features/orders/actions.js +56 -2
  26. package/dist/_internal/server/features/orders/adapters.d.ts +20 -2
  27. package/dist/_internal/server/features/orders/adapters.js +44 -0
  28. package/dist/_internal/server/features/orders/cancellation-refund.d.ts +116 -0
  29. package/dist/_internal/server/features/orders/cancellation-refund.js +466 -0
  30. package/dist/_internal/server/features/orders/index.d.ts +2 -1
  31. package/dist/_internal/server/features/orders/index.js +1 -1
  32. package/dist/_internal/server/features/orders/service.d.ts +60 -0
  33. package/dist/_internal/server/features/orders/service.js +74 -0
  34. package/dist/_internal/server/features/payment-cases/disputes.d.ts +76 -0
  35. package/dist/_internal/server/features/payment-cases/disputes.js +241 -0
  36. package/dist/_internal/server/features/payment-cases/index.d.ts +9 -0
  37. package/dist/_internal/server/features/payment-cases/index.js +9 -0
  38. package/dist/_internal/server/features/payouts/actions.d.ts +28 -3
  39. package/dist/_internal/server/features/payouts/actions.js +84 -10
  40. package/dist/_internal/server/features/points/adjust.d.ts +61 -0
  41. package/dist/_internal/server/features/points/adjust.js +121 -0
  42. package/dist/_internal/server/features/points/award.d.ts +65 -0
  43. package/dist/_internal/server/features/points/award.js +145 -0
  44. package/dist/_internal/server/features/price-index/market.d.ts +33 -0
  45. package/dist/_internal/server/features/price-index/market.js +54 -1
  46. package/dist/_internal/server/features/products/data.js +40 -22
  47. package/dist/_internal/server/features/protection-claims/actions.d.ts +72 -0
  48. package/dist/_internal/server/features/protection-claims/actions.js +228 -0
  49. package/dist/_internal/server/features/protection-claims/index.d.ts +8 -0
  50. package/dist/_internal/server/features/protection-claims/index.js +8 -0
  51. package/dist/_internal/server/features/refunds/actions.d.ts +20 -0
  52. package/dist/_internal/server/features/refunds/actions.js +259 -17
  53. package/dist/_internal/server/features/refunds/capacity.d.ts +29 -0
  54. package/dist/_internal/server/features/refunds/capacity.js +37 -0
  55. package/dist/_internal/server/features/reviews/actions.js +3 -2
  56. package/dist/_internal/server/features/search/index-build/sources.js +20 -1
  57. package/dist/_internal/server/features/shipping/reconcile.d.ts +10 -1
  58. package/dist/_internal/server/features/shipping/reconcile.js +34 -3
  59. package/dist/_internal/server/features/shipping/reimbursement.d.ts +117 -0
  60. package/dist/_internal/server/features/shipping/reimbursement.js +223 -0
  61. package/dist/_internal/server/features/stores/tabs.d.ts +19 -4
  62. package/dist/_internal/server/features/stores/tabs.js +24 -4
  63. package/dist/_internal/server/functions/https.d.ts +31 -1
  64. package/dist/_internal/server/functions/https.js +52 -1
  65. package/dist/_internal/server/functions/scheduled.d.ts +72 -1
  66. package/dist/_internal/server/functions/scheduled.js +124 -1
  67. package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +62 -16
  68. package/dist/_internal/server/jobs/core/boxRollupReconcile.d.ts +46 -0
  69. package/dist/_internal/server/jobs/core/boxRollupReconcile.js +142 -0
  70. package/dist/_internal/server/jobs/core/dailyDataCleanup.js +149 -1
  71. package/dist/_internal/server/jobs/core/dailyStatusDigest.d.ts +14 -0
  72. package/dist/_internal/server/jobs/core/dailyStatusDigest.js +79 -1
  73. package/dist/_internal/server/jobs/core/index.d.ts +2 -0
  74. package/dist/_internal/server/jobs/core/index.js +2 -0
  75. package/dist/_internal/server/jobs/core/marketPriceRollup.d.ts +64 -0
  76. package/dist/_internal/server/jobs/core/marketPriceRollup.js +153 -0
  77. package/dist/_internal/server/jobs/core/obligationSweep.d.ts +36 -0
  78. package/dist/_internal/server/jobs/core/obligationSweep.js +503 -0
  79. package/dist/_internal/server/jobs/core/paymentReconcile.d.ts +79 -0
  80. package/dist/_internal/server/jobs/core/paymentReconcile.js +614 -0
  81. package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +34 -0
  82. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +35 -4
  83. package/dist/_internal/server/jobs/handlers/boxRollupReconcile.d.ts +2 -0
  84. package/dist/_internal/server/jobs/handlers/boxRollupReconcile.js +15 -0
  85. package/dist/_internal/server/jobs/handlers/countersReconcileNow.d.ts +65 -0
  86. package/dist/_internal/server/jobs/handlers/countersReconcileNow.js +89 -0
  87. package/dist/_internal/server/jobs/handlers/index.d.ts +5 -0
  88. package/dist/_internal/server/jobs/handlers/index.js +5 -0
  89. package/dist/_internal/server/jobs/handlers/marketPriceRollup.d.ts +2 -0
  90. package/dist/_internal/server/jobs/handlers/marketPriceRollup.js +2 -0
  91. package/dist/_internal/server/jobs/handlers/obligationSweep.d.ts +2 -0
  92. package/dist/_internal/server/jobs/handlers/obligationSweep.js +15 -0
  93. package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.js +30 -1
  94. package/dist/_internal/server/jobs/handlers/paymentReconcile.d.ts +2 -0
  95. package/dist/_internal/server/jobs/handlers/paymentReconcile.js +6 -0
  96. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  97. package/dist/_internal/shared/actions/action-registry.js +71 -0
  98. package/dist/_internal/shared/checkout/coupon-discount.d.ts +73 -0
  99. package/dist/_internal/shared/checkout/coupon-discount.js +103 -0
  100. package/dist/_internal/shared/checkout/lanes.d.ts +42 -0
  101. package/dist/_internal/shared/checkout/lanes.js +46 -0
  102. package/dist/_internal/shared/checkout/order-math.d.ts +149 -1
  103. package/dist/_internal/shared/checkout/order-math.js +251 -3
  104. package/dist/_internal/shared/checkout/refundable-base.d.ts +116 -0
  105. package/dist/_internal/shared/checkout/refundable-base.js +122 -0
  106. package/dist/_internal/shared/features/auctions/config.d.ts +14 -1
  107. package/dist/_internal/shared/features/auctions/config.js +30 -1
  108. package/dist/_internal/shared/features/brands/schema.d.ts +42 -0
  109. package/dist/_internal/shared/features/brands/schema.js +18 -0
  110. package/dist/_internal/shared/features/orders/refund-copy.d.ts +22 -0
  111. package/dist/_internal/shared/features/orders/refund-copy.js +34 -0
  112. package/dist/_internal/shared/features/print/label-profiles.d.ts +198 -0
  113. package/dist/_internal/shared/features/print/label-profiles.js +350 -0
  114. package/dist/_internal/shared/features/products/to-product-item.js +33 -5
  115. package/dist/_internal/shared/fees/calculator.d.ts +31 -2
  116. package/dist/_internal/shared/fees/calculator.js +103 -5
  117. package/dist/_internal/shared/fees/india-states.d.ts +195 -0
  118. package/dist/_internal/shared/fees/india-states.js +190 -0
  119. package/dist/_internal/shared/fees/payout-hold.d.ts +80 -0
  120. package/dist/_internal/shared/fees/payout-hold.js +74 -0
  121. package/dist/_internal/shared/obligations/deadlines.d.ts +94 -0
  122. package/dist/_internal/shared/obligations/deadlines.js +155 -0
  123. package/dist/_internal/shared/shipping/quote.d.ts +96 -0
  124. package/dist/_internal/shared/shipping/quote.js +67 -0
  125. package/dist/_internal/shared/time/business-days.d.ts +91 -0
  126. package/dist/_internal/shared/time/business-days.js +185 -0
  127. package/dist/cli/index.js +0 -2
  128. package/dist/client.d.ts +10 -4
  129. package/dist/client.js +29 -3
  130. package/dist/configs/tailwind.d.ts +0 -12
  131. package/dist/configs/tailwind.js +28 -15
  132. package/dist/constants/api-endpoints.d.ts +51 -9
  133. package/dist/constants/api-endpoints.js +23 -7
  134. package/dist/constants/index.d.ts +1 -1
  135. package/dist/constants/index.js +1 -1
  136. package/dist/contracts/index.d.ts +1 -1
  137. package/dist/contracts/payment.d.ts +131 -0
  138. package/dist/features/about/components/AboutView.js +1 -1
  139. package/dist/features/about/components/DeveloperView.js +5 -2
  140. package/dist/features/about/components/FAQPageView.js +2 -1
  141. package/dist/features/about/components/FeesView.js +2 -1
  142. package/dist/features/about/components/HelpPageView.js +2 -1
  143. package/dist/features/about/components/HowAuctionsWorkView.js +2 -1
  144. package/dist/features/about/components/HowCheckoutWorksView.js +2 -1
  145. package/dist/features/about/components/HowEmiWorksView.js +2 -1
  146. package/dist/features/about/components/HowOffersWorkView.js +2 -1
  147. package/dist/features/about/components/HowOrdersWorkView.js +2 -1
  148. package/dist/features/about/components/HowPayoutsWorkView.js +2 -1
  149. package/dist/features/about/components/HowPreOrdersWorkView.js +2 -1
  150. package/dist/features/about/components/HowReviewsWorkView.js +2 -1
  151. package/dist/features/about/components/PolicyPageView.js +2 -1
  152. package/dist/features/about/components/ProseHero.d.ts +73 -0
  153. package/dist/features/about/components/ProseHero.js +18 -0
  154. package/dist/features/about/components/SecurityPrivacyView.js +2 -1
  155. package/dist/features/about/components/ShippingPolicyView.js +2 -1
  156. package/dist/features/about/components/TrackOrderView.js +2 -1
  157. package/dist/features/about/components/UnauthorizedView.js +1 -1
  158. package/dist/features/about/index.d.ts +2 -0
  159. package/dist/features/about/index.js +5 -0
  160. package/dist/features/account/actions/address-actions.d.ts +26 -2
  161. package/dist/features/account/actions/address-actions.js +25 -1
  162. package/dist/features/account/components/BuyerShoppingGuideView.js +1 -1
  163. package/dist/features/account/components/NotificationPreferencesPanel.js +1 -1
  164. package/dist/features/account/components/UserOrdersView.js +17 -0
  165. package/dist/features/account/components/UserSidebar.js +1 -1
  166. package/dist/features/account/hooks/useNotifications.js +29 -0
  167. package/dist/features/admin/actions/admin-coupon-actions.js +36 -0
  168. package/dist/features/admin/components/AdminBeysView.js +2 -2
  169. package/dist/features/admin/components/AdminBlogEditorView.js +2 -2
  170. package/dist/features/admin/components/AdminBrandEditorView.js +32 -2
  171. package/dist/features/admin/components/AdminBundleEditorView.js +1 -1
  172. package/dist/features/admin/components/AdminCarouselEditorView.js +1 -1
  173. package/dist/features/admin/components/AdminCategoriesView.js +1 -1
  174. package/dist/features/admin/components/AdminCategoryEditorView.js +73 -17
  175. package/dist/features/admin/components/AdminContactEditorView.js +1 -1
  176. package/dist/features/admin/components/AdminCouponEditorView.js +26 -1
  177. package/dist/features/admin/components/AdminFaqEditorView.js +1 -1
  178. package/dist/features/admin/components/AdminFaqsView.js +2 -2
  179. package/dist/features/admin/components/AdminGatewayEventsView.d.ts +54 -0
  180. package/dist/features/admin/components/AdminGatewayEventsView.js +209 -0
  181. package/dist/features/admin/components/AdminGuideHubView.js +1 -1
  182. package/dist/features/admin/components/AdminMoneyCasesView.d.ts +60 -0
  183. package/dist/features/admin/components/AdminMoneyCasesView.js +287 -0
  184. package/dist/features/admin/components/AdminPartsView.js +2 -2
  185. package/dist/features/admin/components/AdminProductsView.js +75 -4
  186. package/dist/features/admin/components/AdminSidebar.js +2 -2
  187. package/dist/features/admin/components/AdminSiteSettingsView.js +65 -7
  188. package/dist/features/admin/components/AdminSublistingCategoriesView.js +2 -0
  189. package/dist/features/admin/components/AdminSupportTicketDetailView.js +1 -1
  190. package/dist/features/admin/components/AdminSupportTicketsView.js +2 -2
  191. package/dist/features/admin/components/AdminTesterChecklistView.js +2 -2
  192. package/dist/features/admin/components/AdminUsersView.js +72 -1
  193. package/dist/features/admin/components/AdminViewCards.d.ts +3 -1
  194. package/dist/features/admin/components/AdminViewCards.js +4 -4
  195. package/dist/features/admin/components/DataListingView.d.ts +28 -0
  196. package/dist/features/admin/components/DataListingView.js +175 -14
  197. package/dist/features/admin/components/DataTable.d.ts +12 -1
  198. package/dist/features/admin/components/DataTable.js +3 -3
  199. package/dist/features/admin/components/OwnerQuickActions.d.ts +1 -1
  200. package/dist/features/admin/components/OwnerQuickActions.js +60 -2
  201. package/dist/features/admin/components/RecordOwnerQuickActions.d.ts +1 -1
  202. package/dist/features/admin/components/RecordOwnerQuickActions.js +61 -14
  203. package/dist/features/admin/components/analytics/AdminStatCard.d.ts +35 -1
  204. package/dist/features/admin/components/analytics/AdminStatCard.js +77 -2
  205. package/dist/features/admin/components/index.d.ts +4 -0
  206. package/dist/features/admin/components/index.js +6 -0
  207. package/dist/features/admin/constants/filter-tabs.d.ts +156 -0
  208. package/dist/features/admin/constants/filter-tabs.js +106 -0
  209. package/dist/features/admin/repository/site-settings.repository.d.ts +22 -0
  210. package/dist/features/admin/repository/site-settings.repository.js +82 -1
  211. package/dist/features/admin/schemas/admin-editor-forms.d.ts +21 -0
  212. package/dist/features/admin/schemas/admin-editor-forms.js +44 -0
  213. package/dist/features/admin/schemas/firestore.js +5 -1
  214. package/dist/features/admin/schemas/site-settings-form.js +30 -1
  215. package/dist/features/auctions/actions/bid-actions.js +13 -1
  216. package/dist/features/auctions/components/AuctionBottomActions.js +2 -2
  217. package/dist/features/auctions/components/AuctionDetailPageView.js +3 -1
  218. package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +11 -0
  219. package/dist/features/auctions/components/MarketplaceAuctionCard.js +5 -3
  220. package/dist/features/auctions/components/PlaceBidFormClient.d.ts +8 -1
  221. package/dist/features/auctions/components/PlaceBidFormClient.js +2 -2
  222. package/dist/features/audit-log/schemas/firestore.d.ts +28 -0
  223. package/dist/features/audit-log/schemas/firestore.js +14 -0
  224. package/dist/features/auth/permissions/constants.d.ts +17 -1
  225. package/dist/features/auth/permissions/constants.js +18 -0
  226. package/dist/features/blog/components/BlogPostView.js +1 -1
  227. package/dist/features/catalogue/components/AdminCatalogueApprovalsView.js +1 -1
  228. package/dist/features/categories/api/[id]/description-template/route.js +107 -1
  229. package/dist/features/categories/components/BrandDetailPageView.js +2 -2
  230. package/dist/features/categories/components/BreadcrumbTrail.js +7 -1
  231. package/dist/features/categories/components/BundleDetailView.js +1 -1
  232. package/dist/features/categories/components/CategoryDetailPageView.js +2 -2
  233. package/dist/features/categories/components/CategoryForm.js +12 -1
  234. package/dist/features/categories/components/CategoryTemplatePicker.js +38 -5
  235. package/dist/features/categories/repository/market-price-index.repository.d.ts +123 -0
  236. package/dist/features/categories/repository/market-price-index.repository.js +105 -0
  237. package/dist/features/categories/repository/price-observation.repository.d.ts +166 -0
  238. package/dist/features/categories/repository/price-observation.repository.js +132 -0
  239. package/dist/features/events/components/EventSaleBanner.js +1 -1
  240. package/dist/features/events/components/EventStatusBadge.js +1 -1
  241. package/dist/features/faq/components/FAQAccordion.js +2 -1
  242. package/dist/features/faq/components/FAQCategorySidebar.js +2 -2
  243. package/dist/features/faq/components/FAQHelpfulButtons.js +4 -4
  244. package/dist/features/faq/components/RelatedFAQs.js +1 -1
  245. package/dist/features/filters/FilterFacetSection.js +1 -1
  246. package/dist/features/filters/SwitchFilter.js +1 -1
  247. package/dist/features/gateway-events/repository/gateway-events.repository.d.ts +117 -0
  248. package/dist/features/gateway-events/repository/gateway-events.repository.js +274 -0
  249. package/dist/features/gateway-events/schemas/firestore.d.ts +217 -0
  250. package/dist/features/gateway-events/schemas/firestore.js +125 -0
  251. package/dist/features/gateway-events/schemas/index.d.ts +81 -0
  252. package/dist/features/gateway-events/schemas/index.js +79 -0
  253. package/dist/features/grouped/components/GroupedListingDetailView.js +1 -1
  254. package/dist/features/homepage/components/AnnouncementBar.js +37 -1
  255. package/dist/features/homepage/components/AnnouncementBar.style.css +30 -0
  256. package/dist/features/homepage/components/BrandsSection.js +1 -1
  257. package/dist/features/homepage/components/CTABannerSection.js +1 -1
  258. package/dist/features/homepage/components/FeaturedBundlesSection.js +14 -24
  259. package/dist/features/homepage/components/HeroCarousel.js +2 -2
  260. package/dist/features/homepage/components/SocialPostCard.js +1 -1
  261. package/dist/features/inventory/components/AdminMoveLedgerView.d.ts +7 -0
  262. package/dist/features/inventory/components/AdminMoveLedgerView.js +157 -0
  263. package/dist/features/inventory/components/AdminStorageBoxesView.d.ts +11 -0
  264. package/dist/features/inventory/components/AdminStorageBoxesView.js +168 -0
  265. package/dist/features/inventory/components/ReceiveStationView.d.ts +39 -0
  266. package/dist/features/inventory/components/ReceiveStationView.js +413 -0
  267. package/dist/features/inventory/components/operator-message.d.ts +29 -0
  268. package/dist/features/inventory/components/operator-message.js +41 -0
  269. package/dist/features/inventory/index.d.ts +13 -0
  270. package/dist/features/inventory/index.js +28 -0
  271. package/dist/features/inventory/repository/inventory-movements.repository.d.ts +97 -0
  272. package/dist/features/inventory/repository/inventory-movements.repository.js +186 -0
  273. package/dist/features/inventory/repository/inventory-placements.repository.d.ts +179 -0
  274. package/dist/features/inventory/repository/inventory-placements.repository.js +345 -0
  275. package/dist/features/inventory/repository/storage-boxes.repository.d.ts +83 -0
  276. package/dist/features/inventory/repository/storage-boxes.repository.js +127 -0
  277. package/dist/features/inventory/schemas/firestore.d.ts +197 -0
  278. package/dist/features/inventory/schemas/firestore.js +159 -0
  279. package/dist/features/layout/AppLayoutShell.d.ts +12 -1
  280. package/dist/features/layout/AppLayoutShell.js +25 -12
  281. package/dist/features/layout/AutoBreadcrumbs.js +162 -3
  282. package/dist/features/layout/AutoBreadcrumbs.style.css +45 -0
  283. package/dist/features/layout/BottomNavbar.d.ts +1 -1
  284. package/dist/features/layout/BottomNavbar.js +2 -2
  285. package/dist/features/media/MediaAvatar.js +1 -1
  286. package/dist/features/media/MediaImage.d.ts +24 -4
  287. package/dist/features/media/MediaImage.js +44 -4
  288. package/dist/features/media/MediaLightbox.js +1 -1
  289. package/dist/features/media/modals/ImageCropModal.js +1 -1
  290. package/dist/features/media/modals/ImageEditor.js +1 -1
  291. package/dist/features/media/upload/MediaUploadField.js +91 -3
  292. package/dist/features/obligations/constants/policies.d.ts +92 -0
  293. package/dist/features/obligations/constants/policies.js +378 -0
  294. package/dist/features/obligations/repository/obligations.repository.d.ts +68 -0
  295. package/dist/features/obligations/repository/obligations.repository.js +158 -0
  296. package/dist/features/obligations/schemas/firestore.d.ts +160 -0
  297. package/dist/features/obligations/schemas/firestore.js +87 -0
  298. package/dist/features/orders/actions/order-actions.d.ts +43 -4
  299. package/dist/features/orders/actions/order-actions.js +60 -3
  300. package/dist/features/orders/actions/refund-actions.js +70 -10
  301. package/dist/features/orders/components/OrderCompletionPanel.d.ts +27 -0
  302. package/dist/features/orders/components/OrderCompletionPanel.js +192 -0
  303. package/dist/features/orders/components/OrdersList.js +2 -2
  304. package/dist/features/orders/components/RefundHistoryTable.js +3 -1
  305. package/dist/features/orders/components/index.d.ts +2 -0
  306. package/dist/features/orders/components/index.js +6 -0
  307. package/dist/features/orders/constants/transitions.d.ts +59 -0
  308. package/dist/features/orders/constants/transitions.js +104 -0
  309. package/dist/features/orders/repository/orders.repository.d.ts +109 -6
  310. package/dist/features/orders/repository/orders.repository.js +464 -21
  311. package/dist/features/orders/schemas/firestore.d.ts +270 -0
  312. package/dist/features/orders/schemas/firestore.js +24 -0
  313. package/dist/features/orders/schemas/index.d.ts +61 -0
  314. package/dist/features/orders/schemas/index.js +22 -0
  315. package/dist/features/orders/types/index.d.ts +79 -0
  316. package/dist/features/parts/components/PartsIndexPageView.js +8 -1
  317. package/dist/features/payment-cases/repository/payment-cases.repository.d.ts +170 -0
  318. package/dist/features/payment-cases/repository/payment-cases.repository.js +342 -0
  319. package/dist/features/payment-cases/schemas/firestore.d.ts +229 -0
  320. package/dist/features/payment-cases/schemas/firestore.js +105 -0
  321. package/dist/features/payment-cases/schemas/resolve-form.d.ts +97 -0
  322. package/dist/features/payment-cases/schemas/resolve-form.js +114 -0
  323. package/dist/features/payments/repository/payout.repository.d.ts +0 -1
  324. package/dist/features/payments/repository/payout.repository.js +0 -1
  325. package/dist/features/points/repository/points.repository.d.ts +122 -0
  326. package/dist/features/points/repository/points.repository.js +304 -1
  327. package/dist/features/points/schemas/adjust-form.d.ts +58 -0
  328. package/dist/features/points/schemas/adjust-form.js +63 -0
  329. package/dist/features/points/schemas/firestore.d.ts +108 -1
  330. package/dist/features/points/schemas/firestore.js +84 -0
  331. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +3 -3
  332. package/dist/features/pre-orders/components/PreOrderBadge.js +1 -1
  333. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +1 -1
  334. package/dist/features/price-index/components/PriceIndexToolView.d.ts +23 -4
  335. package/dist/features/price-index/components/PriceIndexToolView.js +71 -6
  336. package/dist/features/price-index/market-stats.d.ts +82 -0
  337. package/dist/features/price-index/market-stats.js +230 -0
  338. package/dist/features/print/components/BoxLabelPrintView.d.ts +25 -0
  339. package/dist/features/print/components/BoxLabelPrintView.js +66 -0
  340. package/dist/features/print/components/LabelProfilePicker.d.ts +13 -0
  341. package/dist/features/print/components/LabelProfilePicker.js +38 -0
  342. package/dist/features/print/components/labels.d.ts +117 -0
  343. package/dist/features/print/components/labels.js +258 -0
  344. package/dist/features/print/components/labels.style.css +46 -0
  345. package/dist/features/print/index.d.ts +6 -0
  346. package/dist/features/print/index.js +16 -0
  347. package/dist/features/products/columns/productTableColumns.js +5 -4
  348. package/dist/features/products/components/MarketplaceBundleCard.js +2 -2
  349. package/dist/features/products/components/MarketplacePrizeDrawCard.js +6 -6
  350. package/dist/features/products/components/PrizeDrawCollage.js +1 -1
  351. package/dist/features/products/components/PrizeDrawItemsEditor.js +1 -1
  352. package/dist/features/products/components/PrizeRevealModal.js +2 -2
  353. package/dist/features/products/components/ProductDetailPageView.js +18 -4
  354. package/dist/features/products/components/ProductForm.js +34 -23
  355. package/dist/features/products/components/ProductGrid.js +86 -62
  356. package/dist/features/products/constants/card-badges.d.ts +97 -0
  357. package/dist/features/products/constants/card-badges.js +100 -0
  358. package/dist/features/products/repository/products.repository.js +34 -1
  359. package/dist/features/products/schemas/firestore.d.ts +46 -3
  360. package/dist/features/products/schemas/firestore.js +21 -0
  361. package/dist/features/promotions/components/PromotionsView.js +1 -1
  362. package/dist/features/promotions/repository/claimed-coupons.repository.d.ts +32 -0
  363. package/dist/features/promotions/repository/claimed-coupons.repository.js +58 -0
  364. package/dist/features/promotions/schemas/firestore.js +30 -3
  365. package/dist/features/promotions/schemas/index.d.ts +6 -6
  366. package/dist/features/protection-claims/repository/protection-claims.repository.d.ts +54 -0
  367. package/dist/features/protection-claims/repository/protection-claims.repository.js +174 -0
  368. package/dist/features/protection-claims/schemas/firestore.d.ts +168 -0
  369. package/dist/features/protection-claims/schemas/firestore.js +130 -0
  370. package/dist/features/reviews/actions/review-actions.js +3 -2
  371. package/dist/features/reviews/components/ReviewModal.js +1 -1
  372. package/dist/features/reviews/components/ReviewsList.js +1 -1
  373. package/dist/features/reviews/schemas/firestore.d.ts +20 -1
  374. package/dist/features/scams/constants/scam-types.d.ts +2 -0
  375. package/dist/features/scams/constants/scam-types.js +18 -0
  376. package/dist/features/scams/schemas/report-form.d.ts +3 -3
  377. package/dist/features/scams/schemas/report-form.js +26 -1
  378. package/dist/features/search/components/Search.js +9 -9
  379. package/dist/features/search/components/SearchResultsClient.js +18 -3
  380. package/dist/features/search/components/SearchResultsPageView.d.ts +1 -6
  381. package/dist/features/search/components/SearchResultsPageView.js +2 -2
  382. package/dist/features/seller/actions/offer-actions.js +16 -1
  383. package/dist/features/seller/actions/seller-actions.js +14 -3
  384. package/dist/features/seller/components/CategoryInlineSelect.js +75 -11
  385. package/dist/features/seller/components/PrintCenterView.d.ts +5 -0
  386. package/dist/features/seller/components/PrintCenterView.js +41 -30
  387. package/dist/features/seller/components/SellerOrdersView.js +1 -1
  388. package/dist/features/seller/components/SellerPayoutRequestView.js +16 -5
  389. package/dist/features/seller/components/SellerPayoutSettingsView.js +1 -1
  390. package/dist/features/seller/components/SellerProductShell.d.ts +16 -0
  391. package/dist/features/seller/components/SellerProductShell.js +123 -13
  392. package/dist/features/seller/components/SellerReviewsView.js +4 -2
  393. package/dist/features/seller/components/SellerSidebar.js +1 -1
  394. package/dist/features/seller/schemas/coupon-form.d.ts +26 -0
  395. package/dist/features/seller/schemas/coupon-form.js +27 -0
  396. package/dist/features/seller/schemas/product-form.d.ts +3 -0
  397. package/dist/features/seller/schemas/product-form.js +5 -0
  398. package/dist/features/shell/FormShell.js +2 -2
  399. package/dist/features/shell/QuickFormDrawer.js +14 -0
  400. package/dist/features/shell/SectionForm.d.ts +19 -0
  401. package/dist/features/shell/SectionForm.js +133 -9
  402. package/dist/features/shell/SectionForm.style.css +54 -0
  403. package/dist/features/shipments/components/AdminShipmentsView.js +16 -1
  404. package/dist/features/shipments/repository/shipment-items.repository.d.ts +9 -0
  405. package/dist/features/shipments/repository/shipment-items.repository.js +14 -0
  406. package/dist/features/site-settings/components/ActionPermissionsManager.js +1 -1
  407. package/dist/features/sticker-trace/components/StickerCommitPanel.js +1 -1
  408. package/dist/features/store-extensions/schemas/report-review-form.d.ts +8 -8
  409. package/dist/features/stores/components/StoreGuideHubView.js +1 -1
  410. package/dist/features/stores/components/StoreHeader.js +1 -1
  411. package/dist/features/support/schemas/firestore.d.ts +73 -2
  412. package/dist/features/support/schemas/firestore.js +59 -0
  413. package/dist/index.d.ts +16 -24
  414. package/dist/index.js +38 -47
  415. package/dist/next/ErrorBoundary.js +1 -1
  416. package/dist/next/routing/route-map.d.ts +24 -0
  417. package/dist/next/routing/route-map.js +40 -0
  418. package/dist/providers/payment-manual/index.d.ts +15 -1
  419. package/dist/providers/payment-manual/index.js +37 -0
  420. package/dist/providers/payment-phonepe/index.d.ts +14 -1
  421. package/dist/providers/payment-phonepe/index.js +36 -0
  422. package/dist/providers/payment-razorpay/index.d.ts +44 -1
  423. package/dist/providers/payment-razorpay/index.js +99 -0
  424. package/dist/providers/shipping-shiprocket/index.d.ts +18 -0
  425. package/dist/providers/shipping-shiprocket/index.js +18 -0
  426. package/dist/schemas/registry.d.ts +44 -11
  427. package/dist/server-entry.d.ts +2 -0
  428. package/dist/server-entry.js +27 -0
  429. package/dist/server.d.ts +43 -0
  430. package/dist/server.js +98 -0
  431. package/dist/styles.css +418 -149
  432. package/dist/tailwind-utilities.css +1 -1
  433. package/dist/tokens/themes/default-dark.js +15 -12
  434. package/dist/tokens/themes/default-light.js +14 -11
  435. package/dist/tokens/tokens.css +106 -23
  436. package/dist/ui/DataTable.style.css +4 -4
  437. package/dist/ui/columns/cell-renderers.d.ts +20 -0
  438. package/dist/ui/columns/cell-renderers.js +26 -1
  439. package/dist/ui/columns/index.d.ts +1 -1
  440. package/dist/ui/columns/index.js +4 -1
  441. package/dist/ui/components/Badge.style.css +1 -1
  442. package/dist/ui/components/Breadcrumb.js +19 -1
  443. package/dist/ui/components/BulkActionBar.style.css +4 -4
  444. package/dist/ui/components/Button.style.css +1 -1
  445. package/dist/ui/components/Checkbox.style.css +1 -1
  446. package/dist/ui/components/FallbackShell.js +1 -1
  447. package/dist/ui/components/Form.d.ts +14 -1
  448. package/dist/ui/components/Form.js +2 -2
  449. package/dist/ui/components/FormField.js +18 -4
  450. package/dist/ui/components/FormField.style.css +43 -3
  451. package/dist/ui/components/GatedPrice.style.css +1 -1
  452. package/dist/ui/components/IconButton.style.css +1 -1
  453. package/dist/ui/components/Input.js +22 -1
  454. package/dist/ui/components/Input.style.css +38 -22
  455. package/dist/ui/components/ListingFilterDrawer.js +1 -1
  456. package/dist/ui/components/ListingToolbar.js +1 -1
  457. package/dist/ui/components/PaginatedSelect.js +0 -0
  458. package/dist/ui/components/Radio.style.css +1 -1
  459. package/dist/ui/components/Repeater.d.ts +53 -0
  460. package/dist/ui/components/Repeater.js +7 -0
  461. package/dist/ui/components/RichTextEditor.d.ts +20 -1
  462. package/dist/ui/components/RichTextEditor.js +23 -2
  463. package/dist/ui/components/Select.style.css +7 -21
  464. package/dist/ui/components/Semantic.js +27 -3
  465. package/dist/ui/components/TagInput.style.css +4 -9
  466. package/dist/ui/components/Textarea.style.css +4 -18
  467. package/dist/ui/components/Toggle.style.css +1 -1
  468. package/dist/ui/components/Typography.d.ts +3 -3
  469. package/dist/ui/components/Typography.js +15 -15
  470. package/dist/ui/components/ViewToggle.style.css +4 -4
  471. package/dist/ui/forms/AddAnotherToggle.d.ts +16 -0
  472. package/dist/ui/forms/AddAnotherToggle.js +56 -0
  473. package/dist/ui/forms/ColorPickerField.js +15 -2
  474. package/dist/ui/forms/FieldCheckbox.js +15 -2
  475. package/dist/ui/forms/FieldInput.d.ts +22 -1
  476. package/dist/ui/forms/FieldInput.js +19 -5
  477. package/dist/ui/forms/FieldLabel.d.ts +35 -0
  478. package/dist/ui/forms/FieldLabel.js +70 -0
  479. package/dist/ui/forms/FieldSelect.d.ts +4 -1
  480. package/dist/ui/forms/FieldSelect.js +27 -5
  481. package/dist/ui/forms/FieldTextarea.d.ts +4 -1
  482. package/dist/ui/forms/FieldTextarea.js +22 -5
  483. package/dist/ui/forms/FormShell.d.ts +17 -1
  484. package/dist/ui/forms/FormShell.js +36 -2
  485. package/dist/ui/forms/FormShell.style.css +41 -33
  486. package/dist/ui/forms/index.d.ts +5 -1
  487. package/dist/ui/forms/index.js +2 -0
  488. package/dist/ui/icons/icon-registry.d.ts +1 -0
  489. package/dist/ui/icons/icon-registry.js +17 -1
  490. package/dist/utils/id-generators.d.ts +80 -0
  491. package/dist/utils/id-generators.js +93 -0
  492. package/dist/utils/search-txt-builders.d.ts +12 -0
  493. package/dist/utils/search-txt-builders.js +17 -0
  494. package/package.json +1 -1
  495. package/scripts/seed-cli.mjs +106 -5
  496. package/dist/features/loyalty/api/admin/loyalty/grant/route.d.ts +0 -12
  497. package/dist/features/loyalty/api/admin/loyalty/grant/route.js +0 -38
  498. package/dist/features/loyalty/api/balance/route.d.ts +0 -12
  499. package/dist/features/loyalty/api/balance/route.js +0 -41
  500. package/dist/features/loyalty/api/earn/route.d.ts +0 -12
  501. package/dist/features/loyalty/api/earn/route.js +0 -38
  502. package/dist/features/loyalty/api/history/route.d.ts +0 -12
  503. package/dist/features/loyalty/api/history/route.js +0 -58
  504. package/dist/features/loyalty/api/redeem/route.d.ts +0 -12
  505. package/dist/features/loyalty/api/redeem/route.js +0 -38
  506. package/dist/features/loyalty/columns/index.d.ts +0 -17
  507. package/dist/features/loyalty/columns/index.js +0 -40
  508. package/dist/features/loyalty/components/CoinsDisplay.d.ts +0 -12
  509. package/dist/features/loyalty/components/CoinsDisplay.js +0 -10
  510. package/dist/features/loyalty/components/index.d.ts +0 -1
  511. package/dist/features/loyalty/components/index.js +0 -1
  512. package/dist/features/loyalty/hooks/useLoyaltyBalance.d.ts +0 -4
  513. package/dist/features/loyalty/hooks/useLoyaltyBalance.js +0 -25
  514. package/dist/features/loyalty/index.d.ts +0 -6
  515. package/dist/features/loyalty/index.js +0 -6
  516. package/dist/features/loyalty/manifest.d.ts +0 -2
  517. package/dist/features/loyalty/manifest.js +0 -16
  518. package/dist/features/loyalty/messages/en.json +0 -19
  519. package/dist/features/loyalty/repository/loyalty.repository.d.ts +0 -8
  520. package/dist/features/loyalty/repository/loyalty.repository.js +0 -22
  521. package/dist/features/loyalty/schemas/index.d.ts +0 -85
  522. package/dist/features/loyalty/schemas/index.js +0 -40
  523. package/dist/features/loyalty/server.d.ts +0 -6
  524. package/dist/features/loyalty/server.js +0 -6
  525. package/dist/features/loyalty/types/index.d.ts +0 -31
  526. package/dist/features/loyalty/types/index.js +0 -1
  527. package/dist/features/loyalty/types/loyalty-config.d.ts +0 -7
  528. package/dist/features/loyalty/types/loyalty-config.js +0 -1
  529. package/dist/features/loyalty/types/loyalty-math.d.ts +0 -9
  530. package/dist/features/loyalty/types/loyalty-math.js +0 -27
  531. package/dist/features/products/components/ProductOwnerQuickActions.d.ts +0 -11
  532. package/dist/features/products/components/ProductOwnerQuickActions.js +0 -120
@@ -2,6 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import Link from "next/link.js";
4
4
  import { usePathname } from "next/navigation.js";
5
+ import { LISTING_TYPE_REGISTRY } from "../../_internal/shared/listing-types/_registry.js";
5
6
  import { Div, Li, Nav, Ol, Span } from "../../ui/index.js";
6
7
  /** Map of path segments → human-readable labels. */
7
8
  const DEFAULT_PATH_LABELS = {
@@ -28,6 +29,36 @@ const DEFAULT_PATH_LABELS = {
28
29
  view: "View",
29
30
  add: "Add",
30
31
  edit: "Edit",
32
+ /*
33
+ * Real public route segments whose title-cased form is wrong or ugly.
34
+ * Anything absent here still renders — `capitalize()` title-cases every
35
+ * word, so `digital-codes` reads "Digital Codes" unaided. These are only the
36
+ * ones where casing alone does not get there (`faqs` -> "Faqs",
37
+ * `pre-orders` -> "Pre Orders").
38
+ */
39
+ faqs: "FAQs",
40
+ "pre-orders": "Pre-Orders",
41
+ "prize-draws": "Prize Draws",
42
+ "digital-codes": "Digital Codes",
43
+ beys: "Beyblades",
44
+ parts: "Parts",
45
+ brands: "Brands",
46
+ franchise: "Franchise",
47
+ bundles: "Bundles",
48
+ stores: "Stores",
49
+ sellers: "Sellers",
50
+ events: "Events",
51
+ reviews: "Reviews",
52
+ auctions: "Auctions",
53
+ promotions: "Promotions",
54
+ classified: "Classified",
55
+ live: "Live Items",
56
+ art: "Art",
57
+ stickers: "Stickers",
58
+ catalogue: "Catalogue",
59
+ credits: "Credits",
60
+ about: "About",
61
+ contact: "Contact",
31
62
  };
32
63
  // Common locale codes filtered out of path segments
33
64
  const LOCALE_CODES = new Set([
@@ -51,8 +82,89 @@ const LOCALE_CODES = new Set([
51
82
  "pa",
52
83
  "ur",
53
84
  ]);
85
+ /*
86
+ * ── 🛑 THE LAST SEGMENT OF A DETAIL ROUTE IS DATA, NOT A LABEL ─────────────
87
+ *
88
+ * This component only sees `usePathname()`, so it cannot know which segments
89
+ * are dynamic. Title-casing one anyway produced, verbatim in production:
90
+ *
91
+ * Home / Products / Product beyblade x xtreme stadium bx 10
92
+ *
93
+ * while the page's OWN breadcrumb, rendered directly beneath it, correctly
94
+ * read `Xtreme Stadiums › Beyblade X Xtreme Stadium (BX-10)`. Only the page
95
+ * holds the real title; a pathname cannot be turned into one.
96
+ *
97
+ * So an entity id is OMITTED rather than guessed at — the breadcrumb simply
98
+ * ends at `Home / Products`, which is true, useful and navigable.
99
+ *
100
+ * 🛑 CORRECTED 2026-10-21 — this read "Every detail page in this app renders
101
+ * its own trail with real titles, which is why dropping the crumb loses
102
+ * nothing", and that is FALSE. Measured across five detail views: only
103
+ * `ProductDetailPageView` renders one. `AuctionDetailPageView`,
104
+ * `StoreDetailLayoutView`, `BlogPostView` and `BrandDetailPageView` render
105
+ * NONE, so on those four the shortened trail above is the only breadcrumb
106
+ * there is.
107
+ *
108
+ * That does not change the decision — a trail ending at `Home / Auctions` is
109
+ * still correct, and title-casing an id produced
110
+ * `Product beyblade x xtreme stadium bx 10`, which was not. But the
111
+ * justification matters, because the false version invites the obvious next
112
+ * move: "detail pages have their own trail, so suppress this component on
113
+ * detail routes entirely". That would strip the breadcrumb from those four
114
+ * surfaces. The duplicate is handled by `:has()` in
115
+ * `AutoBreadcrumbs.style.css`, which fires only where a page actually
116
+ * renders its own.
117
+ *
118
+ * 🛑 The listing prefixes are READ FROM `LISTING_TYPE_REGISTRY`, never
119
+ * re-listed here. Two enumerations of one union always drift (Root Cause #42 /
120
+ * #61), and that registry is already the single source for all nine listing
121
+ * types' `slugPrefix`.
122
+ *
123
+ * The non-listing prefixes below cannot come from there because no registry
124
+ * covers them; they are the documented slug-prefix system in CLAUDE.md, and
125
+ * only the ones that actually appear in a PUBLIC url are listed — an
126
+ * `order-`/`payout-`/`notif-` id never reaches a public breadcrumb.
127
+ *
128
+ * 🛑 This does NOT catch a prefix-less slug: `/beys/variares-d-d` still renders
129
+ * "Variares D D". That is a known, accepted limitation rather than an
130
+ * oversight — it is readable, it is not an id-shaped string, and the bey page's
131
+ * own breadcrumb carries the proper name. Fixing it properly means the page
132
+ * supplying its leaf label, which is plumbing this component cannot do alone.
133
+ */
134
+ const NON_LISTING_PUBLIC_PREFIXES = [
135
+ "category-",
136
+ "brand-",
137
+ "store-",
138
+ "blog-",
139
+ "event-",
140
+ "review-",
141
+ "faq-",
142
+ "coupon-",
143
+ "group-",
144
+ "sublisting-",
145
+ "user-",
146
+ "mycatalog-",
147
+ "catalog-",
148
+ "scammer-",
149
+ ];
150
+ function isOpaqueEntityId(seg) {
151
+ const listingPrefixes = Object.values(LISTING_TYPE_REGISTRY)
152
+ .map((p) => p.slugPrefix)
153
+ .filter((p) => Boolean(p));
154
+ return [...listingPrefixes, ...NON_LISTING_PUBLIC_PREFIXES].some((p) => seg.startsWith(p));
155
+ }
156
+ /**
157
+ * Title-case a hyphenated path segment — EVERY word, not just the first.
158
+ *
159
+ * The previous implementation uppercased only `charAt(0)`, so a multi-word
160
+ * segment came out as sentence-case mush ("Pre orders", "Digital codes").
161
+ */
54
162
  function capitalize(s) {
55
- return s.charAt(0).toUpperCase() + s.slice(1).replace(/-/g, " ");
163
+ return s
164
+ .split("-")
165
+ .filter(Boolean)
166
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
167
+ .join(" ");
56
168
  }
57
169
  /**
58
170
  * AutoBreadcrumbs — generates breadcrumb navigation automatically from the
@@ -69,15 +181,62 @@ export function AutoBreadcrumbs({ pathLabels, separator = "/", className = "", r
69
181
  const localePrefix = hasLocalePrefix ? `/${rawSegments[0]}` : "";
70
182
  const segments = rawSegments.filter((seg) => !LOCALE_CODES.has(seg.toLowerCase()) &&
71
183
  !/^[0-9a-f-]{8,}$/.test(seg) &&
72
- !/^\d+$/.test(seg));
184
+ !/^\d+$/.test(seg) &&
185
+ /* An entity id carries no label a pathname can recover — see above. */
186
+ !isOpaqueEntityId(seg));
73
187
  if (segments.length === 0)
74
188
  return null;
189
+ /*
190
+ * 🛑 NOT RENDERED INSIDE A DASHBOARD, and the argument is redundancy rather
191
+ * than taste.
192
+ *
193
+ * On `/admin/products` this band reads "Home / Admin / Products" directly
194
+ * above an `<h1>Products</h1>` — which `DataListingView` and `FormShell`
195
+ * both render now — while the sidebar has that group open and its link
196
+ * marked via `activePath`. Three statements of the same position, in a
197
+ * ~38px strip that is NOT sticky, so it scrolls away and contributes
198
+ * nothing after the first screen. It is pure fold cost: measured, the
199
+ * dashboard chrome ran to ~243px before the first row of content.
200
+ *
201
+ * 🛑 The suppression is keyed on being INSIDE A DASHBOARD, never on "is a
202
+ * detail route". A previous version of this file claimed every detail page
203
+ * renders its own trail; measured, only 1 of 5 does — auction, store, blog
204
+ * and brand render none, so a detail-route rule would have stripped the
205
+ * breadcrumb from four public pages that have nothing else. A dashboard has
206
+ * a sidebar and an h1; a public detail page has neither.
207
+ *
208
+ * The regex matches the LOCALE-STRIPPED segments, so it is unaffected by
209
+ * whether a `/en` prefix is present.
210
+ */
211
+ const isDashboard = ["admin", "store", "user"].includes(segments[0]?.toLowerCase() ?? "");
212
+ if (isDashboard)
213
+ return null;
75
214
  const crumbs = segments.map((seg, i) => ({
76
215
  label: labels[seg] ?? capitalize(seg),
77
216
  href: `${localePrefix}/${segments.slice(0, i + 1).join("/")}`,
78
217
  }));
79
218
  const allCrumbs = [{ label: "Home", href: localePrefix || "/" }, ...crumbs];
80
- return (_jsx(Div, { border: "default", className: "border-y /80 backdrop-blur supports-[backdrop-filter]:bg-white/90 dark:supports-[backdrop-filter]:bg-slate-950/85", surface: "default", children: _jsx(Div, { className: "container mx-auto max-w-[1920px] px-[var(--appkit-space-5)] sm:px-[var(--appkit-space-6)] lg:px-[var(--appkit-space-8)]", padding: "y-xs", children: _jsx(Nav, { "aria-label": "Breadcrumb", className: className, children: _jsx(Ol, { className: "flex items-center gap-[var(--appkit-space-2)] flex-wrap", size: "sm", children: allCrumbs.map((crumb, index) => {
219
+ /*
220
+ * 🛑 The `/80` that used to sit in the root className was NOT leading,
221
+ * which is why the hand-sweep that fixed the other 28 missed it and
222
+ * `audit-dead-css-classes` caught it: the regexes assumed
223
+ * `className="/80 …"`, and this was `className="border-y /80 …"`.
224
+ *
225
+ * It is the same codemod residue — a stripped `bg-white/80` leaving its
226
+ * modifier — and the same silent no-op. Dropped rather than restored: the
227
+ * element already takes `surface="default"`, so the translucency it was
228
+ * reaching for belongs in that token, and the two `supports-[…]` rules
229
+ * beside it already handle the backdrop-filter case with their own alphas.
230
+ *
231
+ * 🛑 AND THIS COMMENT LIVES HERE, ABOVE `return`, FOR A REASON. It was
232
+ * written as a `{/* … *␣/}` block between `return (` and the root element —
233
+ * i.e. in EXPRESSION position, where JSX comment syntax is not valid. That
234
+ * does not parse, and it took the whole appkit build down (TS1005 ×3,
235
+ * TS1128, TS1109). A brace-balance check passed it, because `{/* … *␣/}` is
236
+ * brace-balanced; only `tsc` sees it. Never open a JSX comment before the
237
+ * first element.
238
+ */
239
+ return (_jsx(Div, { border: "default", className: "appkit-auto-breadcrumbs border-y backdrop-blur supports-[backdrop-filter]:bg-white/90 dark:supports-[backdrop-filter]:bg-slate-950/85", surface: "default", children: _jsx(Div, { className: "container mx-auto max-w-[1920px] px-[var(--appkit-space-5)] sm:px-[var(--appkit-space-6)] lg:px-[var(--appkit-space-8)]", padding: "y-xs", children: _jsx(Nav, { "aria-label": "Breadcrumb", className: className, children: _jsx(Ol, { className: "flex items-center gap-[var(--appkit-space-2)] flex-wrap", size: "sm", children: allCrumbs.map((crumb, index) => {
81
240
  const isLast = index === allCrumbs.length - 1;
82
241
  return (_jsxs(Li, { layout: "flex-center", gap: "2", children: [isLast ? (_jsx(Span, { "aria-current": "page", color: "primary", children: crumb.label })) : renderLink ? (renderLink(crumb.href, crumb.label)) : (_jsx(Link, { href: crumb.href, className: "text-[var(--appkit-color-text-muted)] hover:text-zinc-950 dark:hover:text-white transition-colors", children: crumb.label })), !isLast && (_jsx(Span, { className: "text-[var(--appkit-color-text-muted)]/90 select-none", color: "muted", "aria-hidden": "true", children: separator }))] }, crumb.href));
83
242
  }) }) }) }) }));
@@ -0,0 +1,45 @@
1
+ /*
2
+ * One breadcrumb per page.
3
+ *
4
+ * `AppLayoutShell` renders `<AutoBreadcrumbs>` on every route, derived from
5
+ * `usePathname()`. Some pages ALSO render their own trail with real entity
6
+ * titles — `ProductDetailPageView`, `CategoryDetailPageView`, the scam
7
+ * registry — and those pages showed two breadcrumbs stacked. `AutoBreadcrumbs`'
8
+ * own header records seeing exactly that in production:
9
+ *
10
+ * Home / Products / Product beyblade x xtreme stadium bx 10
11
+ * Xtreme Stadiums › Beyblade X Xtreme Stadium (BX-10)
12
+ *
13
+ * and responded by shortening the top one rather than hiding it.
14
+ *
15
+ * ── 🛑 WHY CSS AND NOT REACT ────────────────────────────────────────────────
16
+ *
17
+ * A child cannot hide an already-rendered ancestor's sibling. The shell
18
+ * renders `<AutoBreadcrumbs>` BEFORE `{children}`, so a context or a state
19
+ * flag the page sets arrives a frame late — and hiding a full-width strip one
20
+ * frame after paint is a layout shift at the top of the document, which is the
21
+ * exact defect just fixed on the announcement bar (CLS 0.822). The fix cannot
22
+ * be allowed to become the same bug.
23
+ *
24
+ * `:has()` resolves it during the first style pass: no state, no effect, no
25
+ * frame where both are visible.
26
+ *
27
+ * 🛑 AND IT DEGRADES SAFELY. Where `:has()` is unsupported the rule simply
28
+ * does not match and both breadcrumbs render — today's behaviour. That is the
29
+ * right direction for a progressive enhancement: the failure mode is
30
+ * redundancy, never a missing breadcrumb.
31
+ *
32
+ * 🛑 SCOPED TO THE AUTOMATIC ONE. The page's trail is the one with real
33
+ * titles, so the generic one yields. Suppressing by ROUTE instead would have
34
+ * been wrong: only one of five detail views measured actually renders its own
35
+ * trail, so a route-shaped rule would strip the breadcrumb entirely from
36
+ * auction, store, blog and brand pages — see the correction in
37
+ * `AutoBreadcrumbs.tsx`'s header.
38
+ *
39
+ * @tag domain:layout
40
+ * @tag layer:feature
41
+ */
42
+
43
+ body:has(.appkit-page-breadcrumb) .appkit-auto-breadcrumbs {
44
+ display: none;
45
+ }
@@ -72,7 +72,7 @@ export interface BottomNavbarProps {
72
72
  onMoreToggle?: () => void;
73
73
  /** CSS class applied to the active nav item. Default: "text-primary-600 dark:text-primary-400" */
74
74
  activeClassName?: string;
75
- /** CSS class applied to inactive nav items. Default: "text-[var(--appkit-color-text-muted)] text-[var(--appkit-color-text-muted)]" */
75
+ /** CSS class applied to inactive nav items. Default: "text-[var(--appkit-color-text-muted)]" */
76
76
  inactiveClassName?: string;
77
77
  /** CSS class applied to nav icons */
78
78
  iconClassName?: string;
@@ -45,7 +45,7 @@ function BottomNavSlot({ item, isActive, onOpenChildren, activeClassName, inacti
45
45
  *
46
46
  * Pass `user` from your auth context to render the profile slot with avatar.
47
47
  */
48
- export function BottomNavbar({ user, userId, homeHref, shopHref, cartHref, wishlistHref, profileHref, loginHref, onSearchToggle, navItems, onMoreToggle, activeClassName = "text-primary-600 dark:text-primary-400", inactiveClassName = "text-[var(--appkit-color-text-muted)] text-[var(--appkit-color-text-muted)]", iconClassName, labelClassName = "text-[11px] leading-tight font-medium", getRoleBadgeClass, }) {
48
+ export function BottomNavbar({ user, userId, homeHref, shopHref, cartHref, wishlistHref, profileHref, loginHref, onSearchToggle, navItems, onMoreToggle, activeClassName = "text-primary-600 dark:text-primary-400", inactiveClassName = "text-[var(--appkit-color-text-muted)]", iconClassName, labelClassName = "text-[11px] leading-tight font-medium", getRoleBadgeClass, }) {
49
49
  const pathname = usePathname();
50
50
  const wishlistCount = useWishlistCount(userId);
51
51
  const cartCount = useCartCount(!!userId);
@@ -90,5 +90,5 @@ export function BottomNavbar({ user, userId, homeHref, shopHref, cartHref, wishl
90
90
  return (_jsxs(_Fragment, { children: [_jsxs(BottomNavLayout, { ariaLabel: labels.mobileNav, children: [visibleItems.map((item) => (_jsx(Li, { className: "flex-1", children: _jsx(BottomNavSlot, { item: item, isActive: isSlotActive(item), onOpenChildren: (it) => setOpenKey(it.key), activeClassName: activeClassName, inactiveClassName: inactiveClassName, iconClassName: iconClassName, labelClassName: labelClassName, fallbackIcon: defaultIcon }) }, item.key))), cartHref && (_jsx(Li, { className: "flex-1", children: _jsxs(TextLink, { href: cartHref, variant: "none", className: `${slotClassName} ${pathname === cartHref ? activeClassName : inactiveClassName}`, "aria-label": cartCount > 0 ? `${labels.cart}, ${cartCount} items` : labels.cart, children: [_jsxs(Span, { className: "relative", children: [_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z" }) }), cartCount > 0 && (_jsx(Span, { size: "xs", weight: "semibold", className: CLS_COUNT_BADGE, children: cartCount > 9 ? "9+" : cartCount }))] }), _jsx(Span, { className: labelClassName, children: labels.cart })] }) })), _jsx(Li, { className: "flex-1", children: _jsxs("button", { type: "button", onClick: onMoreToggle, className: `${slotClassName} ${inactiveClassName}`, "aria-label": labels.more, children: [_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "w-5 h-5 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 6h16M4 12h16M4 18h16" }) }), _jsx(Span, { className: labelClassName, children: labels.more })] }) })] }), _jsx(Drawer, { isOpen: !!openItem, onClose: () => setOpenKey(null), title: openItem?.label, side: "bottom", children: _jsxs(Ul, { className: "list-none", children: [openItem && (_jsx(Li, { children: _jsx(TextLink, { href: openItem.href, variant: "none", className: "block rounded-md px-[var(--appkit-space-3)] py-[var(--appkit-space-3)] text-[length:var(--appkit-text-sm)] font-medium text-[var(--appkit-color-text)]", children: openItem.label }) })), (openItem?.children ?? []).map((child) => (_jsx(Li, { children: _jsxs(TextLink, { href: child.href, variant: "none", className: "flex items-start gap-[var(--appkit-space-2)] rounded-md px-[var(--appkit-space-3)] py-[var(--appkit-space-3)] text-[length:var(--appkit-text-sm)] text-[var(--appkit-color-text)]", children: [child.icon && (_jsx(Span, { className: "flex-shrink-0 mt-[var(--appkit-space-0-5)]", "aria-hidden": "true", children: child.icon })), _jsxs(Span, { className: "block", children: [_jsx(Span, { weight: "medium", className: "block", children: child.label }), child.description && (_jsx(Span, { size: "xs", color: "muted", className: "block mt-[var(--appkit-space-0-5)] whitespace-normal", children: child.description }))] })] }) }, child.href)))] }) })] }));
91
91
  }
92
92
  return (_jsxs(BottomNavLayout, { ariaLabel: labels.mobileNav, children: [_jsx(Li, { className: "flex-1", children: _jsx(NavItem, { href: homeHref, label: labels.home, icon: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" }) }), isActive: pathname === homeHref, variant: "vertical", activeClassName: activeClassName, inactiveClassName: inactiveClassName, iconClassName: iconClassName, labelClassName: labelClassName }) }), _jsx(Li, { className: "flex-1", children: _jsx(NavItem, { href: shopHref, label: labels.products, icon: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" }) }), isActive: pathname === shopHref, variant: "vertical", activeClassName: activeClassName, inactiveClassName: inactiveClassName, iconClassName: iconClassName, labelClassName: labelClassName }) }), _jsx(Li, { className: "flex-1", children: _jsxs("button", { type: "button", onClick: onSearchToggle, className: `${slotClassName} ${inactiveClassName}`, "aria-label": labels.search, children: [_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }), _jsx(Span, { className: labelClassName, children: labels.search })] }) }), _jsx(Li, { className: "flex-1", children: _jsxs(TextLink, { href: cartHref, variant: "none", className: `${slotClassName} ${pathname === cartHref ? activeClassName : inactiveClassName}`, "aria-label": cartCount > 0 ? `${labels.cart}, ${cartCount} items` : labels.cart, children: [_jsxs(Span, { className: "relative", children: [_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z" }) }), cartCount > 0 && (_jsx(Span, { size: "xs", weight: "semibold", className: CLS_COUNT_BADGE, children: cartCount > 9 ? "9+" : cartCount }))] }), _jsx(Span, { className: labelClassName, children: labels.cart })] }) }), wishlistHref && (_jsx(Li, { className: "flex-1", children: _jsxs(TextLink, { href: wishlistHref, variant: "none", className: `${slotClassName} ${pathname === wishlistHref ? activeClassName : inactiveClassName}`, "aria-label": wishlistCount > 0 ? `${labels.wishlist}, ${wishlistCount} items` : labels.wishlist, children: [_jsxs(Span, { className: "relative", children: [_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4.318 6.318a4.5 4.5 0 0 0 0 6.364L12 20.364l7.682-7.682a4.5 4.5 0 0 0-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 0 0-6.364 0z" }) }), wishlistCount > 0 && (_jsx(Span, { size: "xs", weight: "semibold", className: CLS_COUNT_BADGE, children: wishlistCount > 9 ? "9+" : wishlistCount }))] }), _jsx(Span, { className: labelClassName, children: labels.wishlist })] }) })), _jsx(Li, { className: "flex-1", children: user ? (_jsxs(TextLink, { href: profileHref, variant: "none", className: `${slotClassName} ${pathname === profileHref ? activeClassName : inactiveClassName}`, "aria-label": labels.profile, children: [_jsx(AvatarDisplay, { cropData: user.avatarMetadata ||
93
- (user.photoURL ? { url: user.photoURL, position: { x: 50, y: 50 }, zoom: 1 } : null), size: "sm", alt: user.displayName || "User", displayName: user.displayName, email: user.email }), user.role && (_jsx(Span, { className: `text-[7px] uppercase leading-none ${getRoleBadgeClass ? getRoleBadgeClass(user.role) : "text-[var(--appkit-color-text-muted)] text-[var(--appkit-color-text-muted)]"}`, weight: "semibold", children: user.role }))] })) : (_jsx(NavItem, { href: loginHref, label: labels.profile, icon: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" }) }), isActive: pathname === loginHref, variant: "vertical", activeClassName: activeClassName, inactiveClassName: inactiveClassName, iconClassName: iconClassName, labelClassName: labelClassName })) })] }));
93
+ (user.photoURL ? { url: user.photoURL, position: { x: 50, y: 50 }, zoom: 1 } : null), size: "sm", alt: user.displayName || "User", displayName: user.displayName, email: user.email }), user.role && (_jsx(Span, { className: `text-[7px] uppercase leading-none ${getRoleBadgeClass ? getRoleBadgeClass(user.role) : "text-[var(--appkit-color-text-muted)]"}`, weight: "semibold", children: user.role }))] })) : (_jsx(NavItem, { href: loginHref, label: labels.profile, icon: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" }) }), isActive: pathname === loginHref, variant: "vertical", activeClassName: activeClassName, inactiveClassName: inactiveClassName, iconClassName: iconClassName, labelClassName: labelClassName })) })] }));
94
94
  }
@@ -8,6 +8,6 @@ const sizeClasses = {
8
8
  xl: "w-20 h-20",
9
9
  };
10
10
  export function MediaAvatar({ src, alt, size = "md", className = "", }) {
11
- return (_jsx(Div, { className: `relative ${sizeClasses[size]} overflow-hidden flex-shrink-0 ${className}`, rounded: "full", children: _jsx(MediaImage, { src: src, alt: alt, size: "avatar", objectFit: "cover" }) }));
11
+ return (_jsx(Div, { className: `relative ${sizeClasses[size]} overflow-hidden flex-shrink-0 ${className}`, rounded: "full", children: _jsx(MediaImage, { src: src, alt: alt, size: "avatar", objectFit: "cover", fill: true }) }));
12
12
  }
13
13
  export default MediaAvatar;
@@ -38,11 +38,31 @@ export interface MediaImageProps {
38
38
  *
39
39
  * Pass `'cover'` explicitly where a FILLED box is the component's contract
40
40
  * rather than a preference — a full-bleed backdrop with text over it, or a
41
- * circular avatar. Three call sites do: `MediaAvatar`, and the slide and
42
- * card backgrounds in `HeroCarousel`. A letterboxed backdrop there would put
43
- * the dim overlay and the headline on bare surface.
41
+ * circular avatar. A letterboxed backdrop would put the dim overlay and the
42
+ * headline on bare surface.
43
+ *
44
+ * 🛑 Counted 2026-10-21: **six** call sites, not the three this said —
45
+ * `MediaAvatar`, both `HeroCarousel` backgrounds, `CTABannerSection`,
46
+ * `CustomCardsSection` and `PublicCatalogueItemDetailView`'s thumbnail
47
+ * strip. Four of them also pass `fill`; the two that do not sit in parents
48
+ * whose shape already matches the size's own box.
44
49
  */
45
50
  objectFit?: "cover" | "contain";
51
+ /**
52
+ * Fill the parent's box instead of establishing one from `size`.
53
+ *
54
+ * 🛑 Only for a parent that ALREADY has a definite height — a full-bleed
55
+ * backdrop, a fixed-size avatar circle, a carousel slide. In an auto-height
56
+ * parent this reproduces the exact bug `SIZE_BOX` exists to fix: the image
57
+ * collapses to zero and renders as empty space.
58
+ *
59
+ * The call sites that need it are close to the ones already passing
60
+ * `objectFit="cover"` — a filled box and a cropped fit are usually the same
61
+ * contract stated twice — but the two are NOT the same decision, so they are
62
+ * separate props. `cover` says how to fit; `fill` says where the box comes
63
+ * from.
64
+ */
65
+ fill?: boolean;
46
66
  /**
47
67
  * Emoji or text to show when `src` is undefined.
48
68
  * Falls back to the per-size default icon.
@@ -92,5 +112,5 @@ export interface MediaImageProps {
92
112
  media?: string;
93
113
  }>;
94
114
  }
95
- export declare function MediaImage({ src, alt, size, priority, loading, fetchPriority, objectFit, fallback, className, rounded, shadow, style, sources, onError, }: MediaImageProps): import("react").JSX.Element;
115
+ export declare function MediaImage({ src, alt, size, priority, loading, fetchPriority, objectFit, fallback, className, rounded, shadow, style, sources, onError, fill, }: MediaImageProps): import("react").JSX.Element;
96
116
  export default MediaImage;
@@ -19,6 +19,38 @@ const SIZE_HINTS = {
19
19
  gallery: "(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw",
20
20
  avatar: "(max-width: 640px) 48px, 56px",
21
21
  };
22
+ /**
23
+ * The BOX each size establishes on the wrapper.
24
+ *
25
+ * 🛑 THIS IS THE FIX FOR A DEFECT THAT MADE `size` A LIE. Until 2026-10-21 the
26
+ * `size` prop fed exactly two things — `SIZE_HINTS` (the `sizes` download
27
+ * attribute) and `FALLBACK_ICONS` (which emoji) — and **neither affected
28
+ * layout**. Every render branch was `relative w-full h-full` around an
29
+ * `<Image fill>`, so the component had an unstated contract: the PARENT must
30
+ * supply a definite height. `h-full` against an auto-height parent is 0, and a
31
+ * `fill` child is absolutely positioned and contributes none of its own, so
32
+ * the whole thing collapsed to zero and rendered as blank space.
33
+ *
34
+ * `size="hero"` therefore read as "this is hero-shaped" and produced **zero
35
+ * pixels**. `ProductGrid` worked only because its own call site wraps the
36
+ * image in `aspect-square` — so `card` was correct BY ACCIDENT OF WHERE IT WAS
37
+ * USED, which is why the reported symptom was "anything which is not a card".
38
+ *
39
+ * Same mechanism as Root Cause #68, one component over, and fixed the same
40
+ * way: at the primitive, not at ~100 call sites. A `Record<MediaImageSize, …>`
41
+ * means a seventh size cannot be added without declaring its shape.
42
+ *
43
+ * Call sites that must genuinely fill a parent they have already sized pass
44
+ * `fill` — see that prop.
45
+ */
46
+ const SIZE_BOX = {
47
+ thumbnail: "aspect-square",
48
+ card: "aspect-square",
49
+ gallery: "aspect-square",
50
+ avatar: "aspect-square",
51
+ hero: "aspect-video",
52
+ banner: "aspect-[3/1]",
53
+ };
22
54
  const FALLBACK_ICONS = {
23
55
  thumbnail: "📦",
24
56
  card: "📦",
@@ -67,7 +99,7 @@ function resolveSrcSet(input) {
67
99
  .filter(Boolean)
68
100
  .join(", ");
69
101
  }
70
- export function MediaImage({ src, alt, size = "card", priority = false, loading, fetchPriority, objectFit = "contain", fallback, className, rounded, shadow, style, sources, onError, }) {
102
+ export function MediaImage({ src, alt, size = "card", priority = false, loading, fetchPriority, objectFit = "contain", fallback, className, rounded, shadow, style, sources, onError, fill = false, }) {
71
103
  const [hasError, setHasError] = useState(false);
72
104
  const [isLoaded, setIsLoaded] = useState(false);
73
105
  const [retryCount, setRetryCount] = useState(0);
@@ -75,6 +107,14 @@ export function MediaImage({ src, alt, size = "card", priority = false, loading,
75
107
  const icon = fallback ?? FALLBACK_ICONS[size];
76
108
  const fitClass = objectFit === "contain" ? "object-contain" : "object-cover";
77
109
  const resolvedSrc = resolveMediaUrl(src);
110
+ /*
111
+ * The wrapper's box: the size's own shape by default, the parent's when the
112
+ * caller opts in with `fill`. Shared by all three render branches below so
113
+ * the placeholder, the `<picture>` and the plain `<Image>` cannot disagree
114
+ * about their dimensions — a fallback that occupies a different box from the
115
+ * image it replaces makes a grid jump as things load.
116
+ */
117
+ const boxClass = fill ? "h-full" : SIZE_BOX[size];
78
118
  // Reset error/load/retry state whenever the resolved src actually changes.
79
119
  // Without this, a component instance that hit a load failure once (e.g.
80
120
  // lost the post-upload propagation race above) latches hasError forever,
@@ -106,7 +146,7 @@ export function MediaImage({ src, alt, size = "card", priority = false, loading,
106
146
  onError?.();
107
147
  };
108
148
  if (!resolvedSrc || hasError) {
109
- return (_jsx(Row, { className: `relative w-full h-full overflow-hidden text-zinc-400 text-[length:var(--appkit-text-4xl)]${wrapperExtra ? ` ${wrapperExtra}` : ""}`, align: "center", justify: "center", surface: "subtle", role: "img", "aria-label": alt, children: _jsx(Span, { "aria-hidden": "true", children: icon }) }));
149
+ return (_jsx(Row, { className: `relative w-full ${boxClass} overflow-hidden text-zinc-400 text-[length:var(--appkit-text-4xl)]${wrapperExtra ? ` ${wrapperExtra}` : ""}`, align: "center", justify: "center", surface: "subtle", role: "img", "aria-label": alt, children: _jsx(Span, { "aria-hidden": "true", children: icon }) }));
110
150
  }
111
151
  const isSvg = resolvedSrc.toLowerCase().endsWith(".svg") ||
112
152
  resolvedSrc.includes("image/svg") ||
@@ -123,11 +163,11 @@ export function MediaImage({ src, alt, size = "card", priority = false, loading,
123
163
  // browser must pick the matching `<source>` itself. Loading + decoding hints
124
164
  // come from the consumer's preset.
125
165
  if (sources && sources.length > 0) {
126
- return (_jsxs(Div, { className: `relative w-full h-full overflow-hidden${wrapperExtra ? ` ${wrapperExtra}` : ""}`, style: style, children: [!isLoaded && (_jsx(Div, { className: "absolute inset-0 animate-pulse", surface: "subtle", "aria-hidden": "true" })), _jsxs("picture", { children: [sources.map((source, index) => (_jsx("source", { srcSet: resolveSrcSet(source.srcSet), type: source.type, media: source.media }, `${source.media ?? ""}-${source.type ?? ""}-${index}`))), _jsx("img", { src: requestSrc, alt: alt, loading: loading ?? (priority ? "eager" : "lazy"), fetchPriority: resolvedFetchPriority, decoding: "async",
166
+ return (_jsxs(Div, { className: `relative w-full ${boxClass} overflow-hidden${wrapperExtra ? ` ${wrapperExtra}` : ""}`, style: style, children: [!isLoaded && (_jsx(Div, { className: "absolute inset-0 animate-pulse", surface: "subtle", "aria-hidden": "true" })), _jsxs("picture", { children: [sources.map((source, index) => (_jsx("source", { srcSet: resolveSrcSet(source.srcSet), type: source.type, media: source.media }, `${source.media ?? ""}-${source.type ?? ""}-${index}`))), _jsx("img", { src: requestSrc, alt: alt, loading: loading ?? (priority ? "eager" : "lazy"), fetchPriority: resolvedFetchPriority, decoding: "async",
127
167
  // catalogued primitive for media (variant catalogue allows the inner
128
168
  // <img> here). Object-fit + className come from typed props.
129
169
  className: `absolute inset-0 w-full h-full ${fitClass}`, onLoad: () => setIsLoaded(true), onError: handleError })] })] }));
130
170
  }
131
- return (_jsxs(Div, { className: `relative w-full h-full overflow-hidden${wrapperExtra ? ` ${wrapperExtra}` : ""}`, style: style, children: [!isLoaded && (_jsx(Div, { className: "absolute inset-0 animate-pulse", surface: "subtle", "aria-hidden": "true" })), _jsx(Image, { src: requestSrc, alt: alt, fill: true, priority: priority, fetchPriority: resolvedFetchPriority, loading: loading ?? (priority ? "eager" : "lazy"), className: fitClass, sizes: SIZE_HINTS[size], onLoad: () => setIsLoaded(true), onError: handleError, unoptimized: isSvg })] }));
171
+ return (_jsxs(Div, { className: `relative w-full ${boxClass} overflow-hidden${wrapperExtra ? ` ${wrapperExtra}` : ""}`, style: style, children: [!isLoaded && (_jsx(Div, { className: "absolute inset-0 animate-pulse", surface: "subtle", "aria-hidden": "true" })), _jsx(Image, { src: requestSrc, alt: alt, fill: true, priority: priority, fetchPriority: resolvedFetchPriority, loading: loading ?? (priority ? "eager" : "lazy"), className: fitClass, sizes: SIZE_HINTS[size], onLoad: () => setIsLoaded(true), onError: handleError, unoptimized: isSvg })] }));
132
172
  }
133
173
  export default MediaImage;
@@ -31,7 +31,7 @@ function IconBtn({ onClick, disabled, ariaLabel, ariaCurrent, className, childre
31
31
  }
32
32
  // --- Controls bar sub-components ---------------------------------------------
33
33
  function LightboxControlsBar({ items, index, zoom, isFullscreen, L, goPrev, goNext, zoomIn, zoomOut, resetZoom, toggleFullscreen, onClose, }) {
34
- return (_jsxs(Row, { gap: "xs", className: "bg-black/85 backdrop-blur-sm shrink-0 border-t border-white/10", padding: "inline", align: "center", justify: "center", wrap: true, children: [items.length > 1 && (_jsx(IconBtn, { onClick: (e) => { e.stopPropagation(); goPrev(); }, ariaLabel: L.prevImage, children: _jsx(ChevronLeft, { className: "w-7 h-7" }) })), _jsx(IconBtn, { onClick: zoomOut, disabled: zoom <= MIN_ZOOM, ariaLabel: L.zoomOut, children: _jsx(ZoomOut, { className: "w-7 h-7" }) }), _jsxs(Span, { color: "inverse", size: "xs", className: "/70 w-14 tabular-nums", align: "center", children: [Math.round(zoom * 100), "%"] }), _jsx(IconBtn, { onClick: zoomIn, disabled: zoom >= MAX_ZOOM, ariaLabel: L.zoomIn, children: _jsx(ZoomIn, { className: "w-7 h-7" }) }), zoom > 1 && (_jsx(IconBtn, { onClick: resetZoom, ariaLabel: L.resetZoom, children: _jsx(RotateCcw, { className: "w-7 h-7" }) })), _jsx(Span, { className: "w-px h-6 bg-white/15 mx-1 shrink-0", "aria-hidden": "true" }), _jsxs(Span, { color: "inverse", size: "xs", className: "/60 w-12 tabular-nums", align: "center", children: [index + 1, " / ", items.length] }), _jsx(Span, { className: "w-px h-6 bg-white/15 mx-1 shrink-0", "aria-hidden": "true" }), _jsx(IconBtn, { onClick: toggleFullscreen, ariaLabel: isFullscreen ? L.exitFullscreen : L.enterFullscreen, children: isFullscreen ? _jsx(Minimize, { className: "w-6 h-6" }) : _jsx(Maximize, { className: "w-6 h-6" }) }), _jsx(IconBtn, { onClick: onClose, ariaLabel: L.close, className: CLS_CLOSE_HOVER, children: _jsx(X, { className: "w-7 h-7" }) }), items.length > 1 && (_jsx(IconBtn, { onClick: (e) => { e.stopPropagation(); goNext(); }, ariaLabel: L.nextImage, children: _jsx(ChevronRight, { className: "w-7 h-7" }) }))] }));
34
+ return (_jsxs(Row, { gap: "xs", className: "bg-black/85 backdrop-blur-sm shrink-0 border-t border-white/10", padding: "inline", align: "center", justify: "center", wrap: true, children: [items.length > 1 && (_jsx(IconBtn, { onClick: (e) => { e.stopPropagation(); goPrev(); }, ariaLabel: L.prevImage, children: _jsx(ChevronLeft, { className: "w-7 h-7" }) })), _jsx(IconBtn, { onClick: zoomOut, disabled: zoom <= MIN_ZOOM, ariaLabel: L.zoomOut, children: _jsx(ZoomOut, { className: "w-7 h-7" }) }), _jsxs(Span, { color: "inverse-muted", size: "xs", className: "w-14 tabular-nums", align: "center", children: [Math.round(zoom * 100), "%"] }), _jsx(IconBtn, { onClick: zoomIn, disabled: zoom >= MAX_ZOOM, ariaLabel: L.zoomIn, children: _jsx(ZoomIn, { className: "w-7 h-7" }) }), zoom > 1 && (_jsx(IconBtn, { onClick: resetZoom, ariaLabel: L.resetZoom, children: _jsx(RotateCcw, { className: "w-7 h-7" }) })), _jsx(Span, { className: "w-px h-6 bg-white/15 mx-1 shrink-0", "aria-hidden": "true" }), _jsxs(Span, { color: "inverse-muted", size: "xs", className: "w-12 tabular-nums", align: "center", children: [index + 1, " / ", items.length] }), _jsx(Span, { className: "w-px h-6 bg-white/15 mx-1 shrink-0", "aria-hidden": "true" }), _jsx(IconBtn, { onClick: toggleFullscreen, ariaLabel: isFullscreen ? L.exitFullscreen : L.enterFullscreen, children: isFullscreen ? _jsx(Minimize, { className: "w-6 h-6" }) : _jsx(Maximize, { className: "w-6 h-6" }) }), _jsx(IconBtn, { onClick: onClose, ariaLabel: L.close, className: CLS_CLOSE_HOVER, children: _jsx(X, { className: "w-7 h-7" }) }), items.length > 1 && (_jsx(IconBtn, { onClick: (e) => { e.stopPropagation(); goNext(); }, ariaLabel: L.nextImage, children: _jsx(ChevronRight, { className: "w-7 h-7" }) }))] }));
35
35
  }
36
36
  function LightboxThumbnailStrip({ items, index, onSelect, resetZoom, L, }) {
37
37
  return (_jsx(Row, { surface: "overlay-xl", className: "backdrop-blur-sm overflow-x-auto shrink-0", padding: "inline", justify: "center", gap: "sm", style: { paddingBottom: "calc(0.75rem + env(safe-area-inset-bottom, 0px))" }, children: items.map((item, i) => (_jsx(Button, { type: "button", onClick: () => { onSelect(i); resetZoom(); }, "aria-label": L.imageThumbnail(i + 1), "aria-current": i === index ? "true" : undefined, className: cn("relative shrink-0 w-14 h-14 p-[var(--appkit-space-0)] overflow-hidden rounded-lg border-2 transition-all active:scale-95", i === index ? "border-white opacity-100" : "border-transparent opacity-40 hover:opacity-75"), children: _jsx(MediaImage, { src: item.src, alt: item.alt, size: "thumbnail" }) }, i))) }));
@@ -95,5 +95,5 @@ export function ImageCropModal({ isOpen, imageUrl, onClose, onSave, initialCropD
95
95
  left: `${position.x}%`,
96
96
  top: `${position.y}%`,
97
97
  transform: "translate(-50%, -50%)",
98
- } }), _jsxs(Div, { className: "absolute inset-0 pointer-events-none", children: [_jsx(Div, { layout: "grid", className: "absolute w-full h-full grid-cols-3 grid-rows-3", children: Array.from({ length: 9 }).map((_, i) => (_jsx(Div, { className: "border border-white/20 border-[var(--appkit-color-border)]/30" }, i))) }), _jsxs(Row, { className: "absolute inset-0", align: "center", justify: "center", children: [_jsx(Div, { className: "w-6 h-px", surface: "default" }), _jsx(Div, { className: "absolute h-6 w-px", surface: "default" })] })] })] }), _jsxs(Stack, { gap: "xs", children: [_jsxs(Row, { justify: "between", children: [_jsx(Text, { size: "xs", weight: "medium", children: t("cropZoom") }), _jsxs(Text, { size: "xs", color: "muted", children: [Math.round(zoom * 100), "%"] })] }), _jsxs(Row, { gap: "3", children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setZoom(Math.max(0.1, zoom - 0.1)), "aria-label": t("cropZoomOut"), children: _jsx("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM13 10H7" }) }) }), _jsx(MediaSlider, { value: zoom, min: 0.1, max: 3, step: 0.01, onChange: (v) => setZoom(v), className: "flex-1" }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setZoom(Math.min(3, zoom + 0.1)), "aria-label": t("cropZoomIn"), children: _jsx("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM10 7v3m0 0v3m0-3h3m-3 0H7" }) }) })] }), _jsx(Row, { gap: "sm", children: [0.5, 1, 1.5, 2].map((preset) => (_jsxs(Button, { rounded: "lg", type: "button", variant: "ghost", size: "sm", onClick: () => setZoom(preset), className: "px-[var(--appkit-space-3)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] bg-[var(--appkit-color-surface)] bg-[var(--appkit-color-surface-elevated)]", children: [preset * 100, "%"] }, preset))) })] }), showZoomWarning && (_jsxs(Alert, { variant: "warning", children: [_jsx(Span, { weight: "bold", children: t("cropWarningTitle") }), " ", t("cropWarningMessage")] })), _jsxs(Row, { textSize: "xs", justify: "between", className: "text-[var(--appkit-color-text-muted)] text-[var(--appkit-color-text-muted)]", children: [_jsxs(Span, { children: [t("cropPosition"), ": ", Math.round(position.x), "%, ", Math.round(position.y), "%"] }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: handleReset, className: "text-primary-600 dark:text-primary-400 hover:underline", children: t("cropReset") })] }), _jsxs(Row, { gap: "sm", padding: "t-xs", children: [_jsx(Button, { onClick: handleSave, variant: "primary", className: "flex-1", children: t("cropSave") }), _jsx(Button, { onClick: onClose, variant: "secondary", className: "flex-1", children: t("cropCancel") })] })] }) }));
98
+ } }), _jsxs(Div, { className: "absolute inset-0 pointer-events-none", children: [_jsx(Div, { layout: "grid", className: "absolute w-full h-full grid-cols-3 grid-rows-3", children: Array.from({ length: 9 }).map((_, i) => (_jsx(Div, { className: "border border-white/20 border-[var(--appkit-color-border)]/30" }, i))) }), _jsxs(Row, { className: "absolute inset-0", align: "center", justify: "center", children: [_jsx(Div, { className: "w-6 h-px", surface: "default" }), _jsx(Div, { className: "absolute h-6 w-px", surface: "default" })] })] })] }), _jsxs(Stack, { gap: "xs", children: [_jsxs(Row, { justify: "between", children: [_jsx(Text, { size: "xs", weight: "medium", children: t("cropZoom") }), _jsxs(Text, { size: "xs", color: "muted", children: [Math.round(zoom * 100), "%"] })] }), _jsxs(Row, { gap: "3", children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setZoom(Math.max(0.1, zoom - 0.1)), "aria-label": t("cropZoomOut"), children: _jsx("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM13 10H7" }) }) }), _jsx(MediaSlider, { value: zoom, min: 0.1, max: 3, step: 0.01, onChange: (v) => setZoom(v), className: "flex-1" }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setZoom(Math.min(3, zoom + 0.1)), "aria-label": t("cropZoomIn"), children: _jsx("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM10 7v3m0 0v3m0-3h3m-3 0H7" }) }) })] }), _jsx(Row, { gap: "sm", children: [0.5, 1, 1.5, 2].map((preset) => (_jsxs(Button, { rounded: "lg", type: "button", variant: "ghost", size: "sm", onClick: () => setZoom(preset), className: "px-[var(--appkit-space-3)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] bg-[var(--appkit-color-surface-elevated)]", children: [preset * 100, "%"] }, preset))) })] }), showZoomWarning && (_jsxs(Alert, { variant: "warning", children: [_jsx(Span, { weight: "bold", children: t("cropWarningTitle") }), " ", t("cropWarningMessage")] })), _jsxs(Row, { textSize: "xs", justify: "between", className: "text-[var(--appkit-color-text-muted)]", children: [_jsxs(Span, { children: [t("cropPosition"), ": ", Math.round(position.x), "%, ", Math.round(position.y), "%"] }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: handleReset, className: "text-primary-600 dark:text-primary-400 hover:underline", children: t("cropReset") })] }), _jsxs(Row, { gap: "sm", padding: "t-xs", children: [_jsx(Button, { onClick: handleSave, variant: "primary", className: "flex-1", children: t("cropSave") }), _jsx(Button, { onClick: onClose, variant: "secondary", className: "flex-1", children: t("cropCancel") })] })] }) }));
99
99
  }
@@ -94,5 +94,5 @@ outputFormat = IMAGE_DOWNSCALE_FORMAT, outputQuality = IMAGE_DOWNSCALE_QUALITY,
94
94
  { label: "4:3", ratio: 4 / 3 },
95
95
  { label: "16:9", ratio: 16 / 9 },
96
96
  { label: "3:2", ratio: 3 / 2 },
97
- ].map((preset) => (_jsx(Button, { rounded: "lg", type: "button", variant: "ghost", size: "sm", onClick: () => applyAspectRatio(preset.ratio), className: "px-[var(--appkit-space-3)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] bg-[var(--appkit-color-surface)] bg-[var(--appkit-color-surface-elevated)]", children: preset.label }, preset.label))) })), _jsxs(Row, { gap: "sm", padding: "t-xs", children: [_jsx(Button, { onClick: handleSave, variant: "primary", className: "flex-1", disabled: saving, children: saving ? t("cropSaving") : t("cropSave") }), _jsx(Button, { onClick: onClose, variant: "secondary", className: "flex-1", children: t("cropCancel") })] })] }) }));
97
+ ].map((preset) => (_jsx(Button, { rounded: "lg", type: "button", variant: "ghost", size: "sm", onClick: () => applyAspectRatio(preset.ratio), className: "px-[var(--appkit-space-3)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] bg-[var(--appkit-color-surface-elevated)]", children: preset.label }, preset.label))) })), _jsxs(Row, { gap: "sm", padding: "t-xs", children: [_jsx(Button, { onClick: handleSave, variant: "primary", className: "flex-1", disabled: saving, children: saving ? t("cropSaving") : t("cropSave") }), _jsx(Button, { onClick: onClose, variant: "secondary", className: "flex-1", children: t("cropCancel") })] })] }) }));
98
98
  }