@mohasinac/appkit 3.4.7 → 3.5.0

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 (606) hide show
  1. package/dist/_internal/client/features/classified/ClassifiedDetailView.js +1 -1
  2. package/dist/_internal/client/features/digital-code/CodeRevealPanel.js +1 -1
  3. package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.js +1 -1
  4. package/dist/_internal/client/features/filters/filter-load-options.js +10 -9
  5. package/dist/_internal/client/features/layout/DashboardLayoutClient.d.ts +6 -1
  6. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +11 -4
  7. package/dist/_internal/client/features/live/LiveItemDetailView.js +2 -2
  8. package/dist/_internal/client/features/maintenance/views/AnalysisRunnerView.js +10 -3
  9. package/dist/_internal/client/features/maintenance/views/ServerErrorsListView.js +2 -2
  10. package/dist/_internal/client/scaffolds/DashboardScaffold.js +3 -1
  11. package/dist/_internal/server/features/checkout/actions.d.ts +16 -0
  12. package/dist/_internal/server/features/checkout/actions.js +149 -35
  13. package/dist/_internal/server/features/checkout/bundle-expansion.d.ts +31 -0
  14. package/dist/_internal/server/features/checkout/bundle-expansion.js +41 -0
  15. package/dist/_internal/server/features/lottery/actions.js +14 -4
  16. package/dist/_internal/server/features/maintenance/analyze.js +4 -2
  17. package/dist/_internal/server/features/orders/actions.js +9 -0
  18. package/dist/_internal/server/features/orders/adapters.js +19 -0
  19. package/dist/_internal/server/features/seo/robots.js +1 -1
  20. package/dist/_internal/server/functions/firestore.d.ts +47 -1
  21. package/dist/_internal/server/functions/firestore.js +56 -1
  22. package/dist/_internal/server/functions/scheduled.d.ts +2 -1
  23. package/dist/_internal/server/functions/scheduled.js +9 -1
  24. package/dist/_internal/server/jobs/core/catalogueImageStalenessReminder.d.ts +10 -0
  25. package/dist/_internal/server/jobs/core/catalogueImageStalenessReminder.js +49 -0
  26. package/dist/_internal/server/jobs/core/cleanupRtdbEvents.js +32 -0
  27. package/dist/_internal/server/jobs/core/hardBanCascade.d.ts +26 -0
  28. package/dist/_internal/server/jobs/core/hardBanCascade.js +179 -0
  29. package/dist/_internal/server/jobs/core/index.d.ts +4 -1
  30. package/dist/_internal/server/jobs/core/index.js +4 -1
  31. package/dist/_internal/server/jobs/core/jobRunners.d.ts +28 -0
  32. package/dist/_internal/server/jobs/core/jobRunners.js +37 -0
  33. package/dist/_internal/server/jobs/core/onCatalogueSubmittedForApproval.d.ts +15 -0
  34. package/dist/_internal/server/jobs/core/onCatalogueSubmittedForApproval.js +38 -0
  35. package/dist/_internal/server/jobs/core/onJobCreated.d.ts +22 -0
  36. package/dist/_internal/server/jobs/core/onJobCreated.js +59 -0
  37. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.d.ts +6 -1
  38. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +5 -2
  39. package/dist/_internal/server/jobs/handlers/catalogueImageStalenessReminder.d.ts +2 -0
  40. package/dist/_internal/server/jobs/handlers/catalogueImageStalenessReminder.js +2 -0
  41. package/dist/_internal/server/jobs/handlers/index.d.ts +6 -0
  42. package/dist/_internal/server/jobs/handlers/index.js +8 -0
  43. package/dist/_internal/server/jobs/handlers/onCatalogueSubmittedForApproval.d.ts +12 -0
  44. package/dist/_internal/server/jobs/handlers/onCatalogueSubmittedForApproval.js +20 -0
  45. package/dist/_internal/server/jobs/handlers/onJobCreated.d.ts +3 -0
  46. package/dist/_internal/server/jobs/handlers/onJobCreated.js +9 -0
  47. package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.d.ts +25 -0
  48. package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.js +71 -0
  49. package/dist/_internal/server/jobs/handlers/onShipmentDeleted.d.ts +14 -0
  50. package/dist/_internal/server/jobs/handlers/onShipmentDeleted.js +23 -0
  51. package/dist/_internal/server/jobs/handlers/onShipmentItemWrite.d.ts +17 -0
  52. package/dist/_internal/server/jobs/handlers/onShipmentItemWrite.js +26 -0
  53. package/dist/_internal/server/jobs/handlers/weeklyPayoutEligibility.js +3 -1
  54. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  55. package/dist/_internal/shared/actions/action-registry.js +136 -0
  56. package/dist/_internal/shared/features/blog/schema.d.ts +8 -8
  57. package/dist/_internal/shared/features/brands/schema.d.ts +4 -4
  58. package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +8 -8
  59. package/dist/_internal/shared/features/events/schema.d.ts +4 -4
  60. package/dist/_internal/shared/features/products/schema.d.ts +8 -8
  61. package/dist/_internal/shared/features/promotions/schema.d.ts +4 -4
  62. package/dist/_internal/shared/features/reviews/schema.d.ts +4 -4
  63. package/dist/client/api/useFeatureFlags.d.ts +22 -0
  64. package/dist/client/api/useFeatureFlags.js +27 -0
  65. package/dist/client/observability/reportClientError.js +3 -2
  66. package/dist/client.d.ts +4 -2
  67. package/dist/client.js +2 -1
  68. package/dist/configs/next.js +1 -0
  69. package/dist/constants/api-endpoints.d.ts +279 -3
  70. package/dist/constants/api-endpoints.js +130 -2
  71. package/dist/core/hooks/useSyncManager.js +5 -4
  72. package/dist/errors/conflict-error.d.ts +4 -0
  73. package/dist/errors/conflict-error.js +6 -0
  74. package/dist/errors/index.d.ts +1 -0
  75. package/dist/errors/index.js +1 -0
  76. package/dist/features/about/components/FeesView.js +2 -2
  77. package/dist/features/about/components/HelpPageView.js +2 -2
  78. package/dist/features/about/components/HowAuctionsWorkView.js +2 -2
  79. package/dist/features/about/components/HowCheckoutWorksView.js +2 -2
  80. package/dist/features/about/components/HowEmiWorksView.js +2 -2
  81. package/dist/features/about/components/HowOffersWorkView.js +3 -3
  82. package/dist/features/about/components/HowOrdersWorkView.js +3 -3
  83. package/dist/features/about/components/HowPayoutsWorkView.js +2 -2
  84. package/dist/features/about/components/HowPreOrdersWorkView.js +2 -2
  85. package/dist/features/about/components/HowReviewsWorkView.js +2 -2
  86. package/dist/features/about/components/PublicProfileView.d.ts +8 -1
  87. package/dist/features/about/components/PublicProfileView.js +11 -9
  88. package/dist/features/about/components/SecurityPrivacyView.js +2 -2
  89. package/dist/features/about/components/UnauthorizedView.js +2 -2
  90. package/dist/features/account/components/AddressBook.js +1 -1
  91. package/dist/features/account/components/AddressesIndexListing.js +1 -1
  92. package/dist/features/account/components/NotificationBell.js +5 -5
  93. package/dist/features/account/components/NotificationPreferencesPanel.js +5 -2
  94. package/dist/features/account/components/UserOffersPanel.js +5 -4
  95. package/dist/features/account/components/UserSidebar.js +2 -2
  96. package/dist/features/account/components/UserSupportView.js +3 -3
  97. package/dist/features/account/schemas/index.d.ts +12 -12
  98. package/dist/features/addresses/schemas/index.d.ts +6 -6
  99. package/dist/features/admin/components/AdminAdEditorView.js +3 -3
  100. package/dist/features/admin/components/AdminAddressEditorView.js +3 -3
  101. package/dist/features/admin/components/AdminAdsView.js +3 -3
  102. package/dist/features/admin/components/AdminBlogEditorView.js +1 -1
  103. package/dist/features/admin/components/AdminBlogView.js +12 -15
  104. package/dist/features/admin/components/AdminBrandEditorView.js +1 -1
  105. package/dist/features/admin/components/AdminBrandsView.js +12 -13
  106. package/dist/features/admin/components/AdminBundleEditorView.js +5 -4
  107. package/dist/features/admin/components/AdminBundlesView.js +32 -23
  108. package/dist/features/admin/components/AdminCarouselEditorView.js +5 -5
  109. package/dist/features/admin/components/AdminCarouselView.js +2 -2
  110. package/dist/features/admin/components/AdminCatalogGuideView.js +1 -1
  111. package/dist/features/admin/components/AdminCategoriesView.js +12 -13
  112. package/dist/features/admin/components/AdminCategoryEditorView.js +2 -2
  113. package/dist/features/admin/components/AdminContactEditorView.js +2 -2
  114. package/dist/features/admin/components/AdminCouponEditorView.d.ts +10 -1
  115. package/dist/features/admin/components/AdminCouponEditorView.js +7 -2
  116. package/dist/features/admin/components/AdminCouponsView.js +32 -27
  117. package/dist/features/admin/components/AdminEmployeeEditorView.js +3 -3
  118. package/dist/features/admin/components/AdminFaqEditorView.js +1 -1
  119. package/dist/features/admin/components/AdminFaqsView.js +20 -20
  120. package/dist/features/admin/components/AdminFeatureEditorView.js +5 -5
  121. package/dist/features/admin/components/AdminFeaturesView.js +9 -10
  122. package/dist/features/admin/components/AdminFilterBar.js +1 -1
  123. package/dist/features/admin/components/AdminFulfillmentView.js +4 -4
  124. package/dist/features/admin/components/AdminGuideHubView.js +2 -2
  125. package/dist/features/admin/components/AdminMediaView.js +3 -2
  126. package/dist/features/admin/components/AdminNavigationView.js +1 -1
  127. package/dist/features/admin/components/AdminOrderEditorView.js +3 -3
  128. package/dist/features/admin/components/AdminOrdersView.js +21 -30
  129. package/dist/features/admin/components/AdminPageHeader.js +3 -3
  130. package/dist/features/admin/components/AdminPayoutsView.js +8 -8
  131. package/dist/features/admin/components/AdminPrizeDrawsView.js +8 -9
  132. package/dist/features/admin/components/AdminProductEditorView.d.ts +9 -1
  133. package/dist/features/admin/components/AdminProductEditorView.js +7 -4
  134. package/dist/features/admin/components/AdminProductsView.js +30 -41
  135. package/dist/features/admin/components/AdminReviewsView.js +14 -17
  136. package/dist/features/admin/components/AdminScammerEditorView.js +5 -5
  137. package/dist/features/admin/components/AdminSectionsView.js +3 -3
  138. package/dist/features/admin/components/AdminSessionsView.js +8 -10
  139. package/dist/features/admin/components/AdminSidebar.js +2 -2
  140. package/dist/features/admin/components/AdminSiteSettingsView.js +10 -3
  141. package/dist/features/admin/components/AdminStoreEditorView.js +4 -5
  142. package/dist/features/admin/components/AdminStoresView.js +18 -13
  143. package/dist/features/admin/components/AdminSupportTicketDetailView.js +7 -7
  144. package/dist/features/admin/components/AdminTeamView.js +9 -5
  145. package/dist/features/admin/components/AdminUsersView.js +19 -15
  146. package/dist/features/admin/components/AdminViewCards.js +5 -5
  147. package/dist/features/admin/components/DashboardStats.js +1 -1
  148. package/dist/features/admin/components/DataListingView.js +2 -2
  149. package/dist/features/admin/components/DataTable.js +2 -2
  150. package/dist/features/admin/components/DrawerFormFooter.js +1 -1
  151. package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +2 -2
  152. package/dist/features/admin/components/analytics/AdminStatCard.js +1 -1
  153. package/dist/features/admin/hooks/useAdminListing.d.ts +3 -2
  154. package/dist/features/admin/hooks/useAdminListing.js +8 -2
  155. package/dist/features/admin/permission-map.js +2 -0
  156. package/dist/features/admin/schemas/firestore.d.ts +7 -0
  157. package/dist/features/admin/schemas/firestore.js +4 -0
  158. package/dist/features/auctions/components/AuctionBidsTable.js +1 -1
  159. package/dist/features/auctions/components/AuctionDetailPageView.js +7 -7
  160. package/dist/features/auctions/components/MarketplaceAuctionCard.js +3 -3
  161. package/dist/features/auctions/components/MarketplaceAuctionGrid.js +4 -4
  162. package/dist/features/auctions/components/PlaceBidFormClient.js +1 -1
  163. package/dist/features/auctions/schemas/index.d.ts +16 -16
  164. package/dist/features/auth/permissions/constants.d.ts +1 -1
  165. package/dist/features/auth/permissions/constants.js +2 -0
  166. package/dist/features/auth/schemas/index.d.ts +6 -6
  167. package/dist/features/before-after/schemas/index.d.ts +3 -3
  168. package/dist/features/blog/actions/blog-actions.d.ts +32 -32
  169. package/dist/features/blog/components/BlogFeaturedCard.js +2 -2
  170. package/dist/features/blog/components/BlogIndexListing.js +2 -2
  171. package/dist/features/blog/components/BlogListView.js +4 -4
  172. package/dist/features/blog/components/BlogPostView.js +4 -4
  173. package/dist/features/blog/schemas/index.d.ts +77 -77
  174. package/dist/features/cart/components/CartDrawer.js +2 -2
  175. package/dist/features/catalogue/actions/approve-catalogue-listing.d.ts +12 -0
  176. package/dist/features/catalogue/actions/approve-catalogue-listing.js +50 -0
  177. package/dist/features/catalogue/actions/list-from-catalogue.d.ts +17 -0
  178. package/dist/features/catalogue/actions/list-from-catalogue.js +50 -0
  179. package/dist/features/catalogue/actions/submit-for-approval.d.ts +8 -0
  180. package/dist/features/catalogue/actions/submit-for-approval.js +30 -0
  181. package/dist/features/catalogue/components/AdminCatalogueApprovalsView.d.ts +2 -0
  182. package/dist/features/catalogue/components/AdminCatalogueApprovalsView.js +53 -0
  183. package/dist/features/catalogue/components/CatalogueItemEditorView.d.ts +7 -0
  184. package/dist/features/catalogue/components/CatalogueItemEditorView.js +79 -0
  185. package/dist/features/catalogue/components/PublicCatalogueView.d.ts +5 -0
  186. package/dist/features/catalogue/components/PublicCatalogueView.js +22 -0
  187. package/dist/features/catalogue/components/UserCatalogueView.d.ts +12 -0
  188. package/dist/features/catalogue/components/UserCatalogueView.js +51 -0
  189. package/dist/features/catalogue/index.d.ts +12 -0
  190. package/dist/features/catalogue/index.js +9 -0
  191. package/dist/features/catalogue/repository/catalogue.repository.d.ts +39 -0
  192. package/dist/features/catalogue/repository/catalogue.repository.js +68 -0
  193. package/dist/features/catalogue/schemas/firestore.d.ts +47 -0
  194. package/dist/features/catalogue/schemas/firestore.js +22 -0
  195. package/dist/features/catalogue/schemas/index.d.ts +2 -0
  196. package/dist/features/catalogue/schemas/index.js +2 -0
  197. package/dist/features/catalogue/schemas/validation.d.ts +71 -0
  198. package/dist/features/catalogue/schemas/validation.js +25 -0
  199. package/dist/features/catalogue/utils/freshness.d.ts +10 -0
  200. package/dist/features/catalogue/utils/freshness.js +15 -0
  201. package/dist/features/catalogue/utils/product-from-item.d.ts +15 -0
  202. package/dist/features/catalogue/utils/product-from-item.js +34 -0
  203. package/dist/features/categories/components/BrandDetailPageView.js +1 -1
  204. package/dist/features/categories/components/BrandDetailTabs.js +2 -2
  205. package/dist/features/categories/components/BundleCollage.js +2 -2
  206. package/dist/features/categories/components/BundleItemsPicker.js +3 -2
  207. package/dist/features/categories/components/CategoriesIndexListing.js +8 -6
  208. package/dist/features/categories/components/CategoryBundlesListing.js +10 -4
  209. package/dist/features/categories/components/CategoryDetailPageView.js +1 -1
  210. package/dist/features/categories/components/CategoryDetailTabs.js +2 -2
  211. package/dist/features/categories/components/CategoryGrid.js +3 -3
  212. package/dist/features/categories/components/CategoryProductsListing.js +1 -1
  213. package/dist/features/categories/components/CategorySortSelect.js +1 -1
  214. package/dist/features/categories/components/CategoryStoresListing.js +1 -1
  215. package/dist/features/categories/components/CategoryTableColumns.js +1 -1
  216. package/dist/features/categories/components/CategoryTree.js +2 -2
  217. package/dist/features/categories/components/ConcernCard.js +1 -1
  218. package/dist/features/categories/hooks/useCategories.js +1 -1
  219. package/dist/features/categories/schemas/index.d.ts +32 -32
  220. package/dist/features/classified/components/ClassifiedFilters.js +2 -2
  221. package/dist/features/classified/components/ClassifiedIndexListing.js +9 -3
  222. package/dist/features/collections/schemas/index.d.ts +2 -2
  223. package/dist/features/consultation/components/ConsultationForm.js +1 -1
  224. package/dist/features/consultation/schemas/index.d.ts +10 -10
  225. package/dist/features/contact/components/ContactForm.js +4 -4
  226. package/dist/features/contact/components/ContactInfoSidebar.js +1 -1
  227. package/dist/features/contact/components/ContactPageView.js +2 -1
  228. package/dist/features/copilot/components/AdminCopilotView.js +5 -4
  229. package/dist/features/corporate/schemas/index.d.ts +2 -2
  230. package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +3 -3
  231. package/dist/features/events/components/AdminEventEditorView.js +4 -4
  232. package/dist/features/events/components/AdminEventEntriesView.js +2 -2
  233. package/dist/features/events/components/AdminEventsView.js +8 -8
  234. package/dist/features/events/components/EventBanner.js +1 -1
  235. package/dist/features/events/components/EventCard.js +3 -3
  236. package/dist/features/events/components/EventLeaderboard.js +1 -1
  237. package/dist/features/events/components/EventOfferCard.js +1 -1
  238. package/dist/features/events/components/EventPollWidget.js +6 -5
  239. package/dist/features/events/components/EventRaffleEntryForm.js +1 -1
  240. package/dist/features/events/components/EventRaffleWinnerView.js +5 -5
  241. package/dist/features/events/components/EventRafflesSection.js +1 -1
  242. package/dist/features/events/components/EventSaleBanner.js +1 -1
  243. package/dist/features/events/components/EventsIndexListing.js +4 -2
  244. package/dist/features/events/components/EventsListView.js +2 -2
  245. package/dist/features/events/components/SpinWheelView.js +11 -5
  246. package/dist/features/events/schemas/index.d.ts +100 -100
  247. package/dist/features/faq/actions/faq-actions.d.ts +6 -6
  248. package/dist/features/faq/components/ContactCTA.js +3 -3
  249. package/dist/features/faq/components/FAQCategorySidebar.js +2 -2
  250. package/dist/features/faq/components/FAQHelpfulButtons.js +3 -3
  251. package/dist/features/faq/schemas/index.d.ts +12 -12
  252. package/dist/features/filters/AsyncFacetSection.js +4 -4
  253. package/dist/features/filters/FilterFacetSection.js +8 -8
  254. package/dist/features/filters/RangeFilter.js +2 -2
  255. package/dist/features/filters/SwitchFilter.js +1 -1
  256. package/dist/features/forms/Checkbox.js +2 -8
  257. package/dist/features/forms/Input.js +2 -1
  258. package/dist/features/forms/Radio.js +3 -3
  259. package/dist/features/forms/Select.d.ts +1 -1
  260. package/dist/features/forms/Select.js +3 -2
  261. package/dist/features/forms/Slider.js +5 -11
  262. package/dist/features/forms/Textarea.js +2 -1
  263. package/dist/features/grouped/schemas/index.d.ts +6 -6
  264. package/dist/features/homepage/actions/homepage-section-actions.d.ts +4 -4
  265. package/dist/features/homepage/components/AdvertisementBanner.js +4 -4
  266. package/dist/features/homepage/components/AnnouncementBar.js +3 -3
  267. package/dist/features/homepage/components/BeforeAfterCard.js +1 -1
  268. package/dist/features/homepage/components/BrandsSection.js +9 -9
  269. package/dist/features/homepage/components/CTABannerSection.js +1 -1
  270. package/dist/features/homepage/components/CharacterHotspot.js +4 -4
  271. package/dist/features/homepage/components/CharacterHotspotForm.js +15 -13
  272. package/dist/features/homepage/components/CollectionCardsSection.js +1 -1
  273. package/dist/features/homepage/components/CustomCardsSection.js +6 -6
  274. package/dist/features/homepage/components/CustomerReviewsSection.js +2 -2
  275. package/dist/features/homepage/components/FAQSection.js +2 -2
  276. package/dist/features/homepage/components/FeaturedBundlesSection.js +3 -3
  277. package/dist/features/homepage/components/FeaturedResultsSection.js +2 -2
  278. package/dist/features/homepage/components/GoogleReviewsSection.js +6 -6
  279. package/dist/features/homepage/components/HeroBanner.js +1 -1
  280. package/dist/features/homepage/components/HeroCarousel.js +5 -4
  281. package/dist/features/homepage/components/HeroSection.js +1 -7
  282. package/dist/features/homepage/components/HomepageSkeleton.js +1 -1
  283. package/dist/features/homepage/components/HowItWorksInfoView.js +1 -1
  284. package/dist/features/homepage/components/HowItWorksSection.js +2 -2
  285. package/dist/features/homepage/components/NewsletterBanner.js +2 -2
  286. package/dist/features/homepage/components/NewsletterSection.js +1 -1
  287. package/dist/features/homepage/components/PromoGrid.js +1 -1
  288. package/dist/features/homepage/components/SectionCarousel.js +6 -6
  289. package/dist/features/homepage/components/SecurityHighlightsSection.js +2 -2
  290. package/dist/features/homepage/components/ShopByCategorySection.js +10 -10
  291. package/dist/features/homepage/components/SiteFeaturesSection.js +2 -2
  292. package/dist/features/homepage/components/SocialFeedSection.js +5 -5
  293. package/dist/features/homepage/components/SocialPostCard.js +1 -1
  294. package/dist/features/homepage/components/StatsCounterSection.js +1 -1
  295. package/dist/features/homepage/components/TestimonialsCarousel.js +1 -1
  296. package/dist/features/homepage/components/TrustBadges.js +1 -1
  297. package/dist/features/homepage/components/TrustFeaturesSection.js +2 -2
  298. package/dist/features/homepage/components/TrustIndicatorsSection.js +2 -2
  299. package/dist/features/homepage/components/WelcomeSection.js +2 -2
  300. package/dist/features/homepage/components/WhatsAppCommunitySection.js +1 -1
  301. package/dist/features/homepage/hooks/useActiveAd.js +2 -1
  302. package/dist/features/homepage/schemas/firestore.d.ts +10 -0
  303. package/dist/features/homepage/schemas/index.d.ts +116 -116
  304. package/dist/features/jobs/actions/enqueue-job.d.ts +24 -0
  305. package/dist/features/jobs/actions/enqueue-job.js +44 -0
  306. package/dist/features/jobs/repository/jobs.repository.d.ts +21 -0
  307. package/dist/features/jobs/repository/jobs.repository.js +48 -0
  308. package/dist/features/jobs/schemas/firestore.d.ts +54 -0
  309. package/dist/features/jobs/schemas/firestore.js +24 -0
  310. package/dist/features/layout/AppLayoutShell.js +17 -11
  311. package/dist/features/layout/AutoBreadcrumbs.js +1 -1
  312. package/dist/features/layout/BackToTop.js +2 -2
  313. package/dist/features/layout/BottomActions.js +7 -7
  314. package/dist/features/layout/BottomNavItem.js +2 -2
  315. package/dist/features/layout/BottomNavLayout.js +13 -4
  316. package/dist/features/layout/BottomNavbar.d.ts +9 -1
  317. package/dist/features/layout/BottomNavbar.js +12 -5
  318. package/dist/features/layout/BottomSheet.js +1 -1
  319. package/dist/features/layout/Breadcrumbs.js +1 -1
  320. package/dist/features/layout/FooterLayout.js +2 -2
  321. package/dist/features/layout/NavItem.js +3 -3
  322. package/dist/features/layout/NavbarLayout.js +6 -6
  323. package/dist/features/layout/SidebarLayout.d.ts +3 -0
  324. package/dist/features/layout/SidebarLayout.js +3 -3
  325. package/dist/features/layout/TitleBarLayout.js +4 -4
  326. package/dist/features/live/components/LiveItemFilters.js +2 -2
  327. package/dist/features/live/components/LiveItemsIndexListing.js +3 -3
  328. package/dist/features/lottery/types/index.d.ts +3 -1
  329. package/dist/features/lottery/types/index.js +16 -3
  330. package/dist/features/loyalty/components/CoinsDisplay.js +2 -2
  331. package/dist/features/media/MediaImage.d.ts +6 -1
  332. package/dist/features/media/MediaImage.js +10 -4
  333. package/dist/features/media/MediaLightbox.js +1 -1
  334. package/dist/features/media/MediaPickerModal.js +4 -3
  335. package/dist/features/media/MediaVideo.js +1 -1
  336. package/dist/features/media/modals/ImageCropModal.js +1 -1
  337. package/dist/features/media/modals/ImageEditor.js +1 -1
  338. package/dist/features/media/repository/media-assets.repository.d.ts +9 -0
  339. package/dist/features/media/types/index.d.ts +4 -4
  340. package/dist/features/media/upload/MediaUploadField.js +3 -3
  341. package/dist/features/media/upload/MediaUploadList.js +1 -1
  342. package/dist/features/messages/hooks/useConversation.js +4 -3
  343. package/dist/features/messages/hooks/useConversations.js +2 -1
  344. package/dist/features/messages/schemas/index.d.ts +6 -6
  345. package/dist/features/orders/components/MarketplaceOrderCard.js +1 -1
  346. package/dist/features/orders/components/OrderPaymentSummary.d.ts +16 -0
  347. package/dist/features/orders/components/OrderPaymentSummary.js +32 -0
  348. package/dist/features/orders/components/OrderSiblingPayments.js +1 -1
  349. package/dist/features/orders/components/OrdersList.d.ts +7 -2
  350. package/dist/features/orders/components/OrdersList.js +5 -5
  351. package/dist/features/orders/components/RefundHistoryTable.js +1 -1
  352. package/dist/features/orders/components/RefundRequestView.js +1 -1
  353. package/dist/features/orders/components/index.d.ts +2 -0
  354. package/dist/features/orders/components/index.js +1 -0
  355. package/dist/features/orders/repository/orders.repository.d.ts +8 -0
  356. package/dist/features/orders/repository/orders.repository.js +24 -0
  357. package/dist/features/orders/schemas/firestore.d.ts +59 -0
  358. package/dist/features/orders/schemas/firestore.js +5 -0
  359. package/dist/features/orders/schemas/index.d.ts +91 -40
  360. package/dist/features/orders/schemas/index.js +10 -0
  361. package/dist/features/orders/types/index.d.ts +15 -0
  362. package/dist/features/payments/schemas/index.d.ts +12 -12
  363. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +5 -5
  364. package/dist/features/pre-orders/components/PreOrderActionsClient.js +1 -1
  365. package/dist/features/pre-orders/components/PreOrderBadge.js +1 -1
  366. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +7 -7
  367. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +3 -3
  368. package/dist/features/pre-orders/schemas/index.d.ts +12 -12
  369. package/dist/features/products/columns/productTableColumns.js +2 -2
  370. package/dist/features/products/components/AuctionsIndexListing.js +3 -3
  371. package/dist/features/products/components/CompareOverlay.js +15 -10
  372. package/dist/features/products/components/CustomFieldsEditor.js +2 -2
  373. package/dist/features/products/components/CustomSectionsEditor.js +3 -3
  374. package/dist/features/products/components/FeatureBadge.js +2 -2
  375. package/dist/features/products/components/GroupSettingsPanel.js +5 -4
  376. package/dist/features/products/components/MakeOfferButton.js +4 -4
  377. package/dist/features/products/components/MarketplaceBundleCard.js +3 -2
  378. package/dist/features/products/components/MarketplacePrizeDrawCard.js +1 -1
  379. package/dist/features/products/components/PrizeDrawCollage.js +6 -6
  380. package/dist/features/products/components/PrizeDrawDetailPageView.js +5 -5
  381. package/dist/features/products/components/PrizeDrawEntryActions.js +1 -1
  382. package/dist/features/products/components/PrizeDrawItemsEditor.js +4 -4
  383. package/dist/features/products/components/PrizeDrawsIndexListing.js +11 -4
  384. package/dist/features/products/components/PrizeDrawsSection.js +1 -1
  385. package/dist/features/products/components/PrizeRevealModal.js +9 -4
  386. package/dist/features/products/components/ProductDetailActions.js +2 -1
  387. package/dist/features/products/components/ProductDetailPageView.js +16 -16
  388. package/dist/features/products/components/ProductFeaturesSelector.js +5 -5
  389. package/dist/features/products/components/ProductForm.js +1 -1
  390. package/dist/features/products/components/ProductGalleryClient.js +5 -3
  391. package/dist/features/products/components/ProductGrid.js +11 -11
  392. package/dist/features/products/components/ProductTabs.js +2 -2
  393. package/dist/features/products/components/ProductTabsShell.js +2 -1
  394. package/dist/features/products/components/ProductsIndexListing.js +6 -1
  395. package/dist/features/products/components/ShareButton.js +2 -1
  396. package/dist/features/products/components/ShowGroupSection.js +9 -5
  397. package/dist/features/products/components/SublistingCarouselSection.js +8 -4
  398. package/dist/features/products/constants/action-defs.d.ts +10 -2
  399. package/dist/features/products/constants/action-defs.js +20 -2
  400. package/dist/features/products/schemas/firestore.d.ts +5 -0
  401. package/dist/features/products/schemas/index.d.ts +40 -40
  402. package/dist/features/products/schemas/product-features.validators.d.ts +14 -14
  403. package/dist/features/promotions/components/CouponCard.js +13 -7
  404. package/dist/features/promotions/components/CouponsIndexListing.js +4 -6
  405. package/dist/features/promotions/components/PromotionsView.js +2 -2
  406. package/dist/features/promotions/schemas/index.d.ts +26 -26
  407. package/dist/features/reviews/components/ReviewDetailPageView.js +1 -1
  408. package/dist/features/reviews/components/ReviewDetailShell.js +11 -11
  409. package/dist/features/reviews/components/ReviewModal.js +1 -1
  410. package/dist/features/reviews/components/ReviewsIndexListing.js +2 -2
  411. package/dist/features/reviews/components/ReviewsList.js +2 -2
  412. package/dist/features/reviews/schemas/index.d.ts +22 -22
  413. package/dist/features/scams/components/ScamAwarenessModal.js +2 -2
  414. package/dist/features/scams/components/ScamProfileView.js +3 -3
  415. package/dist/features/scams/components/ScamRegistryView.js +2 -2
  416. package/dist/features/scams/schemas/index.d.ts +20 -20
  417. package/dist/features/search/components/Search.js +9 -9
  418. package/dist/features/search/components/SearchFiltersRow.js +1 -1
  419. package/dist/features/search/components/SearchResultsSection.js +3 -3
  420. package/dist/features/search/components/SearchView.js +1 -1
  421. package/dist/features/search/hooks/useNavSuggestions.js +2 -1
  422. package/dist/features/search/hooks/useSearch.js +2 -2
  423. package/dist/features/search/schemas/index.d.ts +3 -3
  424. package/dist/features/seller/components/BrandInlineSelect.js +2 -2
  425. package/dist/features/seller/components/CategoryInlineSelect.js +2 -2
  426. package/dist/features/seller/components/QuickProductForm.js +1 -1
  427. package/dist/features/seller/components/SellerAddressesView.js +4 -4
  428. package/dist/features/seller/components/SellerAnalyticsAlertsView.js +3 -3
  429. package/dist/features/seller/components/SellerAnalyticsView.js +2 -2
  430. package/dist/features/seller/components/SellerArtView.js +11 -11
  431. package/dist/features/seller/components/SellerAuctionsView.js +11 -11
  432. package/dist/features/seller/components/SellerBidsView.js +3 -3
  433. package/dist/features/seller/components/SellerBundlesView.js +12 -12
  434. package/dist/features/seller/components/SellerClassifiedView.js +11 -11
  435. package/dist/features/seller/components/SellerCouponEditorView.js +2 -2
  436. package/dist/features/seller/components/SellerDigitalCodesView.js +11 -11
  437. package/dist/features/seller/components/SellerFeaturesView.js +4 -4
  438. package/dist/features/seller/components/SellerLiveView.js +11 -11
  439. package/dist/features/seller/components/SellerOffersPanel.js +3 -2
  440. package/dist/features/seller/components/SellerOrdersView.js +2 -2
  441. package/dist/features/seller/components/SellerPayoutMethodsView.js +1 -1
  442. package/dist/features/seller/components/SellerPayoutRequestView.js +6 -5
  443. package/dist/features/seller/components/SellerPayoutSettingsView.js +5 -4
  444. package/dist/features/seller/components/SellerPreOrdersView.js +1 -1
  445. package/dist/features/seller/components/SellerPrizeDrawsView.js +1 -1
  446. package/dist/features/seller/components/SellerProductShell.js +20 -6
  447. package/dist/features/seller/components/SellerProductsCards.js +3 -3
  448. package/dist/features/seller/components/SellerProductsView.js +4 -4
  449. package/dist/features/seller/components/SellerReviewsView.js +7 -6
  450. package/dist/features/seller/components/SellerShippingView.js +2 -1
  451. package/dist/features/seller/components/SellerSidebar.js +5 -5
  452. package/dist/features/seller/components/SellerStickersView.js +11 -11
  453. package/dist/features/seller/components/SellerTemplatesView.js +1 -1
  454. package/dist/features/seller/schemas/index.d.ts +20 -20
  455. package/dist/features/server-errors/schemas/index.d.ts +6 -6
  456. package/dist/features/shell/CommandPalette.d.ts +27 -0
  457. package/dist/features/shell/CommandPalette.js +92 -0
  458. package/dist/features/shell/FormShell.js +4 -3
  459. package/dist/features/shell/QuickFormDrawer.js +3 -2
  460. package/dist/features/shell/StepForm.js +2 -2
  461. package/dist/features/shell/index.d.ts +2 -0
  462. package/dist/features/shell/index.js +1 -0
  463. package/dist/features/shipments/components/AdminShipmentEditorView.d.ts +7 -0
  464. package/dist/features/shipments/components/AdminShipmentEditorView.js +123 -0
  465. package/dist/features/shipments/components/AdminShipmentLotItemsView.d.ts +6 -0
  466. package/dist/features/shipments/components/AdminShipmentLotItemsView.js +96 -0
  467. package/dist/features/shipments/components/AdminShipmentProjectionsView.d.ts +9 -0
  468. package/dist/features/shipments/components/AdminShipmentProjectionsView.js +44 -0
  469. package/dist/features/shipments/components/AdminShipmentsView.d.ts +8 -0
  470. package/dist/features/shipments/components/AdminShipmentsView.js +82 -0
  471. package/dist/features/shipments/components/ShipmentItemLinkModal.d.ts +15 -0
  472. package/dist/features/shipments/components/ShipmentItemLinkModal.js +37 -0
  473. package/dist/features/shipments/hooks/useShipments.d.ts +69 -0
  474. package/dist/features/shipments/hooks/useShipments.js +96 -0
  475. package/dist/features/shipments/index.d.ts +10 -0
  476. package/dist/features/shipments/index.js +7 -0
  477. package/dist/features/shipments/manifest.d.ts +2 -0
  478. package/dist/features/shipments/manifest.js +26 -0
  479. package/dist/features/shipments/repository/shipment-items.repository.d.ts +56 -0
  480. package/dist/features/shipments/repository/shipment-items.repository.js +78 -0
  481. package/dist/features/shipments/repository/shipment-lots.repository.d.ts +48 -0
  482. package/dist/features/shipments/repository/shipment-lots.repository.js +55 -0
  483. package/dist/features/shipments/repository/shipments.repository.d.ts +50 -0
  484. package/dist/features/shipments/repository/shipments.repository.js +77 -0
  485. package/dist/features/shipments/schemas/firestore.d.ts +150 -0
  486. package/dist/features/shipments/schemas/firestore.js +76 -0
  487. package/dist/features/shipments/schemas/index.d.ts +2 -0
  488. package/dist/features/shipments/schemas/index.js +2 -0
  489. package/dist/features/shipments/schemas/validation.d.ts +350 -0
  490. package/dist/features/shipments/schemas/validation.js +96 -0
  491. package/dist/features/shipments/utils/cost-allocation.d.ts +25 -0
  492. package/dist/features/shipments/utils/cost-allocation.js +83 -0
  493. package/dist/features/site-settings/components/ActionPermissionsManager.js +2 -2
  494. package/dist/features/stores/components/InteractiveStoreCard.js +2 -2
  495. package/dist/features/stores/components/StoreAboutView.js +1 -1
  496. package/dist/features/stores/components/StoreAuctionsListing.js +3 -3
  497. package/dist/features/stores/components/StoreAuctionsView.js +1 -1
  498. package/dist/features/stores/components/StoreCapabilitiesGuideView.js +1 -1
  499. package/dist/features/stores/components/StoreClassifiedsListing.js +2 -2
  500. package/dist/features/stores/components/StoreDetailLayoutView.js +1 -1
  501. package/dist/features/stores/components/StoreDigitalCodesListing.js +2 -2
  502. package/dist/features/stores/components/StoreFinanceGuideView.js +2 -2
  503. package/dist/features/stores/components/StoreGuideHubView.js +2 -2
  504. package/dist/features/stores/components/StoreHeader.js +4 -4
  505. package/dist/features/stores/components/StoreLiveItemsListing.js +2 -2
  506. package/dist/features/stores/components/StoreNavTabs.js +2 -2
  507. package/dist/features/stores/components/StoreOrdersGuideView.js +1 -1
  508. package/dist/features/stores/components/StorePreOrdersListing.js +3 -3
  509. package/dist/features/stores/components/StoreProductsListing.js +1 -1
  510. package/dist/features/stores/components/StoreReviewsListing.js +2 -2
  511. package/dist/features/stores/components/StoreReviewsView.js +1 -1
  512. package/dist/features/stores/components/StoreSettingsGuideView.js +1 -1
  513. package/dist/features/stores/components/StoresIndexListing.js +9 -3
  514. package/dist/features/stores/schemas/index.d.ts +10 -10
  515. package/dist/features/support/schemas/index.d.ts +22 -22
  516. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +3 -3
  517. package/dist/features/whatsapp-bot/components/WhatsAppChatButton.js +1 -1
  518. package/dist/features/wishlist/hooks/useWishlistCount.js +1 -2
  519. package/dist/index.d.ts +44 -1
  520. package/dist/index.js +37 -1
  521. package/dist/next/routing/route-map.d.ts +18 -0
  522. package/dist/next/routing/route-map.js +9 -0
  523. package/dist/react/hooks/useVisualViewportInset.d.ts +1 -0
  524. package/dist/react/hooks/useVisualViewportInset.js +59 -0
  525. package/dist/react/index.d.ts +1 -0
  526. package/dist/react/index.js +1 -0
  527. package/dist/repositories/index.d.ts +5 -0
  528. package/dist/repositories/index.js +5 -0
  529. package/dist/schemas/registry.d.ts +398 -364
  530. package/dist/schemas/sieve.d.ts +2 -2
  531. package/dist/schemas/webhooks/google-oauth.d.ts +2 -2
  532. package/dist/schemas/webhooks/razorpay.d.ts +100 -100
  533. package/dist/seed/_helpers/media.js +1 -0
  534. package/dist/seed/actions/demo-seed-actions.d.ts +1 -1
  535. package/dist/seed/catalogue-seed-data.d.ts +2 -0
  536. package/dist/seed/catalogue-seed-data.js +112 -0
  537. package/dist/seed/grouped-listings-seed-data.d.ts +5 -0
  538. package/dist/seed/homepage-sections-seed-data.js +0 -1
  539. package/dist/seed/index.d.ts +2 -0
  540. package/dist/seed/index.js +2 -0
  541. package/dist/seed/manifest.js +6 -0
  542. package/dist/seed/products-preorders-seed-data.d.ts +5 -0
  543. package/dist/seed/shipments-seed-data.d.ts +5 -0
  544. package/dist/seed/shipments-seed-data.js +185 -0
  545. package/dist/server.d.ts +4 -0
  546. package/dist/server.js +5 -0
  547. package/dist/styles.css +75 -19
  548. package/dist/tailwind-utilities.css +1 -1
  549. package/dist/tokens/index.d.ts +0 -2
  550. package/dist/tokens/index.js +0 -2
  551. package/dist/tokens/tokens.css +12 -2
  552. package/dist/ui/DataTable.js +4 -3
  553. package/dist/ui/components/Button.d.ts +4 -1
  554. package/dist/ui/components/Button.js +11 -5
  555. package/dist/ui/components/Checkbox.d.ts +9 -1
  556. package/dist/ui/components/Checkbox.js +5 -2
  557. package/dist/ui/components/ClaimCouponButton.js +2 -1
  558. package/dist/ui/components/ConfirmDeleteModal.style.css +1 -1
  559. package/dist/ui/components/Drawer.style.css +13 -1
  560. package/dist/ui/components/Dropdown.style.css +2 -2
  561. package/dist/ui/components/FilterDrawer.d.ts +4 -1
  562. package/dist/ui/components/FilterDrawer.js +8 -2
  563. package/dist/ui/components/Form.d.ts +1 -1
  564. package/dist/ui/components/Form.js +2 -2
  565. package/dist/ui/components/FormActionBar.style.css +6 -1
  566. package/dist/ui/components/IconButton.d.ts +6 -1
  567. package/dist/ui/components/IconButton.js +5 -2
  568. package/dist/ui/components/IconButton.style.css +11 -0
  569. package/dist/ui/components/ImageGallery.style.css +2 -0
  570. package/dist/ui/components/ImageLightbox.style.css +1 -0
  571. package/dist/ui/components/ListingFilterDrawer.d.ts +4 -1
  572. package/dist/ui/components/ListingFilterDrawer.js +4 -3
  573. package/dist/ui/components/ListingLayout.style.css +2 -2
  574. package/dist/ui/components/Modal.style.css +1 -1
  575. package/dist/ui/components/Pagination.d.ts +5 -1
  576. package/dist/ui/components/Pagination.js +4 -2
  577. package/dist/ui/components/RowActionMenu.js +1 -1
  578. package/dist/ui/components/RowActionMenu.style.css +1 -1
  579. package/dist/ui/components/Select.d.ts +6 -1
  580. package/dist/ui/components/Select.js +18 -13
  581. package/dist/ui/components/Select.style.css +1 -1
  582. package/dist/ui/components/Semantic.d.ts +13 -0
  583. package/dist/ui/components/Semantic.js +16 -3
  584. package/dist/ui/components/SideDrawer.style.css +16 -4
  585. package/dist/ui/components/SideModal.style.css +1 -1
  586. package/dist/ui/components/StickyToolbar.d.ts +3 -2
  587. package/dist/ui/components/StickyToolbar.js +1 -1
  588. package/dist/ui/components/Textarea.d.ts +5 -0
  589. package/dist/ui/components/Textarea.js +8 -4
  590. package/dist/ui/components/Toast.style.css +3 -0
  591. package/dist/ui/components/Typography.js +69 -8
  592. package/dist/ui/components/UnsavedChangesModal.style.css +1 -1
  593. package/dist/ui/components/surface-tokens.d.ts +121 -113
  594. package/dist/ui/components/surface-tokens.js +110 -104
  595. package/dist/ui/forms/FormShell.d.ts +8 -27
  596. package/dist/ui/forms/FormShell.js +1 -194
  597. package/dist/ui/forms/index.d.ts +2 -2
  598. package/dist/ui/forms/index.js +1 -1
  599. package/dist/ui/index.d.ts +8 -4
  600. package/dist/ui/index.js +4 -2
  601. package/dist/utils/id-generators.d.ts +27 -0
  602. package/dist/utils/id-generators.js +45 -0
  603. package/dist/utils/number.formatter.d.ts +7 -0
  604. package/dist/utils/number.formatter.js +9 -0
  605. package/dist/validation/schemas.d.ts +5 -5
  606. package/package.json +1 -1
@@ -2,10 +2,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import Link from "next/link";
3
3
  import { orderRepository, productRepository } from "../../../repositories";
4
4
  const __P = {
5
- p3: "p-3",
6
- p4: "p-4",
5
+ p3: "p-[var(--appkit-space-3)]",
6
+ p4: "p-[var(--appkit-space-4)]",
7
7
  };
8
- const CLS_PRIZE_BADGE = "inline-block rounded-full bg-fuchsia-100 dark:bg-fuchsia-900/30 px-2.5 py-0.5 text-fuchsia-700 dark:text-fuchsia-300";
8
+ const CLS_PRIZE_BADGE = "inline-block rounded-full bg-fuchsia-100 dark:bg-fuchsia-900/30 px-[var(--appkit-space-2-5)] py-[var(--appkit-space-0-5)] text-fuchsia-700 dark:text-fuchsia-300";
9
9
  import { ROUTES } from "../../../next";
10
10
  import { getDefaultCurrency } from "../../../core/baseline-resolver";
11
11
  import { normalizeRichTextHtml } from "../../../utils/string.formatter";
@@ -66,7 +66,7 @@ export async function PrizeDrawDetailPageView({ id, initialPrizeDraw, currentUse
66
66
  ? initialPrizeDraw ?? undefined
67
67
  : await productRepository.findByIdOrSlug(id).catch(() => undefined);
68
68
  if (!product) {
69
- return (_jsx(Main, { children: _jsx(Section, { padding: "y-5xl", children: _jsx(Container, { size: "md", children: _jsxs(Stack, { align: "center", gap: "md", className: "text-center", children: [_jsx(Heading, { level: 1, size: "2xl", weight: "semibold", color: "primary", children: "Prize Draw Not Found" }), _jsx(Text, { color: "muted", children: "The prize draw you are looking for may have been removed." }), _jsx(Link, { href: String(ROUTES.PUBLIC.PRIZE_DRAWS), className: "text-sm font-medium text-primary-600 hover:underline", children: "Browse Prize Draws" })] }) }) }) }));
69
+ return (_jsx(Main, { children: _jsx(Section, { padding: "y-5xl", children: _jsx(Container, { size: "md", children: _jsxs(Stack, { align: "start", gap: "md", className: "text-left", children: [_jsx(Heading, { level: 1, size: "2xl", weight: "semibold", color: "primary", children: "Prize Draw Not Found" }), _jsx(Text, { color: "muted", children: "The prize draw you are looking for may have been removed." }), _jsx(Link, { href: String(ROUTES.PUBLIC.PRIZE_DRAWS), className: "text-[length:var(--appkit-text-sm)] font-medium text-primary-600 hover:underline", children: "Browse Prize Draws" })] }) }) }) }));
70
70
  }
71
71
  const p = product;
72
72
  const currency = p.currency || getDefaultCurrency();
@@ -118,5 +118,5 @@ export async function PrizeDrawDetailPageView({ id, initialPrizeDraw, currentUse
118
118
  price: pricePerEntry,
119
119
  storeId: typeof p.storeId === "string" ? p.storeId : undefined,
120
120
  storeName: storeName ?? undefined,
121
- } }), _jsxs(Container, { size: "xl", padding: "y-lg", children: [_jsxs(Row, { className: "mb-4", align: "center", justify: "between", gap: "sm", wrap: true, children: [_jsxs("nav", { "aria-label": "Breadcrumb", className: "flex items-center gap-1.5 text-xs text-[var(--appkit-color-text-muted)] flex-wrap", children: [_jsx(Link, { href: String(ROUTES.HOME), className: "hover:text-primary-600 transition-colors", children: "Home" }), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.PRIZE_DRAWS), className: "hover:text-primary-600 transition-colors", children: "Prize Draws" }), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Span, { className: "truncate max-w-[200px]", color: "muted", children: title })] }), _jsx(ShareButton, { title: title })] }), _jsx(PreOrderDetailView, { renderGallery: () => (_jsx(PrizeDrawCollage, { items: items, hideWonState: true })), renderInfo: () => (_jsxs(Stack, { gap: "md", children: [_jsxs(Div, { children: [_jsxs(Row, { gap: "xs", wrap: true, className: "mb-2", children: [_jsx(Span, { size: "xs", weight: "semibold", className: CLS_PRIZE_BADGE, children: "Prize Draw" }), _jsx(Span, { size: "xs", weight: "semibold", className: `inline-block ${statusClass(revealStatus)}`, padding: "pill-sm", rounded: "full", children: statusLabel(revealStatus) }), maxPerUser !== null && (_jsxs(Span, { size: "xs", weight: "medium", className: "inline-block", padding: "pill-sm", rounded: "full", surface: "subtle", color: "muted", children: ["Limit: ", maxPerUser, " entries per customer"] })), maxPerUser !== null && userEntriesUsed !== null && (_jsxs(Span, { size: "xs", weight: "semibold", className: CLS_PRIZE_BADGE, children: ["You have used ", userEntriesUsed, "/", maxPerUser] }))] }), _jsx(Heading, { level: 1, className: "leading-snug", smSize: "2xl", color: "primary", size: "xl", weight: "bold", children: title })] }), _jsx(Div, { className: `${__P.p4}`, border: "subtle", rounded: "xl", surface: "muted", children: _jsxs(Stack, { gap: "sm", children: [_jsxs(Row, { justify: "between", align: "center", children: [_jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "Entries" }), _jsxs(Text, { size: "sm", weight: "semibold", children: [current, " / ", max, " (", remaining, " left)"] })] }), revealStart && (_jsxs(Row, { justify: "between", align: "center", children: [_jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "Reveal window opens" }), _jsx(Text, { size: "sm", weight: "medium", children: revealStart.toLocaleString() })] })), revealEnd && (_jsxs(Row, { justify: "between", align: "center", children: [_jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "Reveal window closes" }), _jsx(Text, { size: "sm", weight: "medium", children: revealEnd.toLocaleString() })] }))] }) }), descriptionHtml && (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-sm leading-relaxed text-[var(--appkit-color-text-muted)] line-clamp-4" })), safeSeller && (_jsx(Div, { className: `${__P.p3}`, border: "subtle", rounded: "xl", surface: "muted", children: _jsxs(Row, { justify: "between", align: "center", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-[10px] tracking-wide mb-0.5", color: "faint", transform: "uppercase", children: "Sold by" }), _jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: safeSeller })] }), storeHref && (_jsx(Link, { href: storeHref, className: "shrink-0 rounded-lg bg-primary/10 dark:bg-primary/20 px-3 py-1.5 text-xs font-semibold text-primary-700 dark:text-primary-300 hover:bg-primary/20 dark:hover:bg-primary/30 transition-colors", children: "Visit Store \u2192" }))] }) }))] })), renderTabs: () => (_jsx(ProductTabsShell, { descriptionContent: descriptionHtml ? (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm sm:prose max-w-none dark:prose-invert", className: "text-[var(--appkit-color-text-muted)]" })) : undefined })), renderBuyBar: () => (_jsx(Div, { padding: "5", id: "prize-draw-buy-bar", border: "subtle", surface: "muted", rounded: "xl", children: _jsx(PrizeDrawEntryActions, { productId: String(product.id), productSlug: slug, title: title, thumb: thumb, pricePerEntry: pricePerEntry, currency: currency, remainingEntries: remaining, revealStatus: revealStatus, prizeGithubFileUrl: githubUrl, storeId: typeof p.storeId === "string" ? p.storeId : undefined, storeName: storeName ?? undefined }) })) }), _jsx(PrizeDrawBottomActions, { pricePerEntry: pricePerEntry, currency: currency, closed: revealStatus === "closed" || remaining === 0 })] })] }));
121
+ } }), _jsxs(Container, { size: "xl", padding: "y-lg", children: [_jsxs(Row, { className: "mb-4", align: "center", justify: "between", gap: "sm", wrap: true, children: [_jsxs("nav", { "aria-label": "Breadcrumb", className: "flex items-center gap-[var(--appkit-space-1-5)] text-[length:var(--appkit-text-xs)] text-[var(--appkit-color-text-muted)] flex-wrap", children: [_jsx(Link, { href: String(ROUTES.HOME), className: "hover:text-primary-600 transition-colors", children: "Home" }), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.PRIZE_DRAWS), className: "hover:text-primary-600 transition-colors", children: "Prize Draws" }), _jsx(Span, { "aria-hidden": true, children: "/" }), _jsx(Span, { className: "truncate max-w-[200px]", color: "muted", children: title })] }), _jsx(ShareButton, { title: title })] }), _jsx(PreOrderDetailView, { renderGallery: () => (_jsx(PrizeDrawCollage, { items: items, hideWonState: true })), renderInfo: () => (_jsxs(Stack, { gap: "md", children: [_jsxs(Div, { children: [_jsxs(Row, { gap: "xs", wrap: true, className: "mb-2", children: [_jsx(Span, { size: "xs", weight: "semibold", className: CLS_PRIZE_BADGE, children: "Prize Draw" }), _jsx(Span, { size: "xs", weight: "semibold", className: `inline-block ${statusClass(revealStatus)}`, padding: "pill-sm", rounded: "full", children: statusLabel(revealStatus) }), maxPerUser !== null && (_jsxs(Span, { size: "xs", weight: "medium", className: "inline-block", padding: "pill-sm", rounded: "full", surface: "subtle", color: "muted", children: ["Limit: ", maxPerUser, " entries per customer"] })), maxPerUser !== null && userEntriesUsed !== null && (_jsxs(Span, { size: "xs", weight: "semibold", className: CLS_PRIZE_BADGE, children: ["You have used ", userEntriesUsed, "/", maxPerUser] }))] }), _jsx(Heading, { level: 1, className: "leading-snug", smSize: "2xl", color: "primary", size: "xl", weight: "bold", children: title })] }), _jsx(Div, { className: `${__P.p4}`, border: "subtle", rounded: "xl", surface: "muted", children: _jsxs(Stack, { gap: "sm", children: [_jsxs(Row, { justify: "between", align: "center", children: [_jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "Entries" }), _jsxs(Text, { size: "sm", weight: "semibold", children: [current, " / ", max, " (", remaining, " left)"] })] }), revealStart && (_jsxs(Row, { justify: "between", align: "center", children: [_jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "Reveal window opens" }), _jsx(Text, { size: "sm", weight: "medium", children: revealStart.toLocaleString() })] })), revealEnd && (_jsxs(Row, { justify: "between", align: "center", children: [_jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "Reveal window closes" }), _jsx(Text, { size: "sm", weight: "medium", children: revealEnd.toLocaleString() })] }))] }) }), descriptionHtml && (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-[length:var(--appkit-text-sm)] leading-relaxed text-[var(--appkit-color-text-muted)] line-clamp-4" })), safeSeller && (_jsx(Div, { className: `${__P.p3}`, border: "subtle", rounded: "xl", surface: "muted", children: _jsxs(Row, { justify: "between", align: "center", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-[10px] tracking-wide mb-0.5", color: "faint", transform: "uppercase", children: "Sold by" }), _jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: safeSeller })] }), storeHref && (_jsx(Link, { href: storeHref, className: "shrink-0 rounded-lg bg-primary/10 dark:bg-primary/20 px-[var(--appkit-space-3)] py-[var(--appkit-space-1-5)] text-[length:var(--appkit-text-xs)] font-semibold text-primary-700 dark:text-primary-300 hover:bg-primary/20 dark:hover:bg-primary/30 transition-colors", children: "Visit Store \u2192" }))] }) }))] })), renderTabs: () => (_jsx(ProductTabsShell, { descriptionContent: descriptionHtml ? (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm sm:prose max-w-none dark:prose-invert", className: "text-[var(--appkit-color-text-muted)]" })) : undefined })), renderBuyBar: () => (_jsx(Div, { padding: "5", id: "prize-draw-buy-bar", border: "subtle", surface: "muted", rounded: "xl", children: _jsx(PrizeDrawEntryActions, { productId: String(product.id), productSlug: slug, title: title, thumb: thumb, pricePerEntry: pricePerEntry, currency: currency, remainingEntries: remaining, revealStatus: revealStatus, prizeGithubFileUrl: githubUrl, storeId: typeof p.storeId === "string" ? p.storeId : undefined, storeName: storeName ?? undefined }) })) }), _jsx(PrizeDrawBottomActions, { pricePerEntry: pricePerEntry, currency: currency, closed: revealStatus === "closed" || remaining === 0 })] })] }));
122
122
  }
@@ -31,5 +31,5 @@ export function PrizeDrawEntryActions({ productId, productSlug, title, thumb: _t
31
31
  const slug = productSlug ?? productId;
32
32
  router.push(`${String(ROUTES.USER.CHECKOUT)}?directItem=${encodeURIComponent(slug)}&type=prize-draw`);
33
33
  }, [productSlug, productId, router]);
34
- return (_jsxs(Stack, { gap: "md", children: [_jsxs(Text, { size: "2xl", weight: "bold", color: "primary", children: [formatCurrency(pricePerEntry, currency), _jsx(Text, { as: "span", className: "ml-1 text-[var(--appkit-color-text-muted)]", size: "xs", weight: "normal", children: "per entry" })] }), _jsx(Button, { action: closed ? undefined : ACTIONS.PRIZE_DRAW["buy-now"], variant: "primary", size: "md", className: "w-full", disabled: closed, onClick: handleEnter, children: closed ? "Draw closed" : undefined }), prizeGithubFileUrl ? (_jsx(Anchor, { href: prizeGithubFileUrl, tone: "none", underline: "hover", size: "xs", weight: "medium", className: "text-center text-primary-600 underline-offset-4 dark:text-primary-400", children: "View RNG source code on GitHub \u2192" })) : null, _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "xs", align: "center", children: "Winners chosen by Node.js crypto.randomInt \u2014 fully auditable. Entries are locked once paid; refunds only if the prize pool is exhausted." }), _jsx(NonRefundableConsentModal, { open: consentOpen, listingType: "prize-draw", itemTitle: title, priceLabel: formatCurrency(pricePerEntry, currency), onCancel: () => setConsentOpen(false), onConfirm: handleConfirm }), _jsx(LoginRequiredModal, { isOpen: modalOpen, onClose: closeModal, message: modalMessage })] }));
34
+ return (_jsxs(Stack, { gap: "md", children: [_jsxs(Text, { size: "2xl", weight: "bold", color: "primary", children: [formatCurrency(pricePerEntry, currency), _jsx(Text, { as: "span", className: "ml-1 text-[var(--appkit-color-text-muted)]", size: "xs", weight: "normal", children: "per entry" })] }), _jsx(Button, { action: closed ? undefined : ACTIONS.PRIZE_DRAW["buy-now"], variant: "primary", size: "md", className: "w-full", disabled: closed, onClick: handleEnter, children: closed ? "Draw closed" : undefined }), prizeGithubFileUrl ? (_jsx(Anchor, { href: prizeGithubFileUrl, tone: "none", underline: "hover", size: "xs", weight: "medium", className: "text-left text-primary-600 underline-offset-4 dark:text-primary-400", children: "View RNG source code on GitHub \u2192" })) : null, _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "xs", align: "start", children: "Winners chosen by Node.js crypto.randomInt \u2014 fully auditable. Entries are locked once paid; refunds only if the prize pool is exhausted." }), _jsx(NonRefundableConsentModal, { open: consentOpen, listingType: "prize-draw", itemTitle: title, priceLabel: formatCurrency(pricePerEntry, currency), onCancel: () => setConsentOpen(false), onConfirm: handleConfirm }), _jsx(LoginRequiredModal, { isOpen: modalOpen, onClose: closeModal, message: modalMessage })] }));
35
35
  }
@@ -11,9 +11,9 @@ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
11
11
  * Min 3 items, max 16 (mirrors PrizeDrawItem schema constraints).
12
12
  */
13
13
  import { useCallback } from "react";
14
- import { Button, Div, FormField, Heading, Row, Span, Stack, Text } from "../../../ui";
15
- const CLS_WARN_BOX = "rounded border border-warning/40 bg-warning-surface px-3 py-2 text-sm text-warning dark:bg-warning-surface dark:text-warning";
16
- const CLS_WON_BADGE = "rounded bg-error-surface px-3 py-1 text-xs font-semibold uppercase tracking-wide text-white";
14
+ import { Button, Div, FormField, Heading, Input, Row, Span, Stack, Text } from "../../../ui";
15
+ const CLS_WARN_BOX = "rounded border border-warning/40 bg-warning-surface px-[var(--appkit-space-3)] py-[var(--appkit-space-2)] text-[length:var(--appkit-text-sm)] text-warning dark:bg-warning-surface dark:text-warning";
16
+ const CLS_WON_BADGE = "rounded bg-error-surface px-[var(--appkit-space-3)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] font-semibold uppercase tracking-wide text-white";
17
17
  import { ImageUpload } from "../../media";
18
18
  const MIN_ITEMS = 3;
19
19
  const MAX_ITEMS = 16;
@@ -95,7 +95,7 @@ export function PrizeDrawItemsEditor({ items, onChange, onUploadImage, onUploadV
95
95
  }), disabled: locked, placeholder: "2999" }) })] }), _jsxs(Stack, { gap: "xs", children: [_jsxs(Text, { size: "sm", weight: "medium", children: ["Images (", (it.images ?? []).length, "/", MAX_IMAGES_PER_ITEM, ")"] }), _jsx(Row, { gap: "sm", wrap: true, children: Array.from({ length: MAX_IMAGES_PER_ITEM }).map((_, slot) => {
96
96
  const existing = (it.images ?? [])[slot];
97
97
  return (_jsxs(Div, { className: "w-40", children: [_jsx(ImageUpload, { currentImage: existing, label: existing ? "Replace" : `Image ${slot + 1}`, onUpload: (file) => onUploadImage(file, it.itemNumber), onChange: (url) => setImage(index, slot, url) }), existing && !locked ? (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => removeImage(index, slot), children: "Remove" })) : null] }, slot));
98
- }) })] }), onUploadVideo ? (_jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", weight: "medium", children: "Video (optional)" }), _jsx("input", { type: "file", accept: "video/*", disabled: locked, onChange: (e) => handleVideoFileChange(e, index, it.itemNumber) }), it.video?.url ? (_jsxs(Text, { className: "text-[var(--appkit-color-text-muted)] truncate", size: "xs", children: ["Current: ", it.video.url] })) : null] })) : null] })] }, `prize-item-${it.itemNumber}-${index}`));
98
+ }) })] }), onUploadVideo ? (_jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", weight: "medium", children: "Video (optional)" }), _jsx(Input, { bare: true, type: "file", accept: "video/*", disabled: locked, onChange: (e) => handleVideoFileChange(e, index, it.itemNumber) }), it.video?.url ? (_jsxs(Text, { className: "text-[var(--appkit-color-text-muted)] truncate", size: "xs", children: ["Current: ", it.video.url] })) : null] })) : null] })] }, `prize-item-${it.itemNumber}-${index}`));
99
99
  }) }), items.length < MIN_ITEMS ? (_jsxs(Div, { textSize: "sm", className: "border border-error/40", color: "error", surface: "danger-surface", padding: "inlineSm", rounded: "default", children: ["At least ", MIN_ITEMS, " prizes are required."] })) : null] }));
100
100
  }
101
101
  export default PrizeDrawItemsEditor;
@@ -4,7 +4,7 @@ import { useState, useCallback } from "react";
4
4
  import { useUrlTable } from "../../../react/hooks/useUrlTable";
5
5
  import { usePendingTable } from "../../../react/hooks/usePendingTable";
6
6
  import { useProducts } from "../hooks/useProducts";
7
- import { Div, FilterDrawer, Label, ListingToolbar, Pagination, Row, Span, Stack, Text } from "../../../ui";
7
+ import { Div, FilterDrawer, Label, ListingToolbar, Pagination, Row, Select, Stack, Text } from "../../../ui";
8
8
  import { useCategoryTree, categoriesToFacetOptions } from "../../categories/hooks/useCategoryTree";
9
9
  import { useBrands } from "../hooks/useBrands";
10
10
  import { MarketplacePrizeDrawCard } from "./MarketplacePrizeDrawCard";
@@ -13,7 +13,7 @@ import { TABLE_KEYS, VIEW_MODE } from "../../../constants/table-keys";
13
13
  import { PRIZE_DRAW_SORT_OPTIONS } from "../constants/sieve";
14
14
  import { PRODUCT_FIELDS } from "../../../constants/field-names";
15
15
  const __P = {
16
- p3: "p-3",
16
+ p3: "p-[var(--appkit-space-3)]",
17
17
  };
18
18
  const DEFAULT_SORT = PRIZE_DRAW_SORT_OPTIONS[0].value;
19
19
  const FILTER_KEYS = [
@@ -78,7 +78,7 @@ export function PrizeDrawsIndexListing({ initialData, categorySlug, brandName, s
78
78
  if (e.key === "Enter")
79
79
  commitSearch();
80
80
  };
81
- const gridClass = "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4";
81
+ const gridClass = "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-[var(--appkit-space-4)]";
82
82
  return (_jsxs(Div, { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: filterActiveCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search prize draws...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, onSearchKeyDown: handleSearchKeyDown, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: PRIZE_DRAW_SORT_OPTIONS, onSortChange: (v) => {
83
83
  table.set(TABLE_KEYS.SORT, v);
84
84
  }, view: view, onViewChange: (v) => {
@@ -86,5 +86,12 @@ export function PrizeDrawsIndexListing({ initialData, categorySlug, brandName, s
86
86
  return;
87
87
  setView(v);
88
88
  table.set(TABLE_KEYS.VIEW, v);
89
- }, onResetAll: resetAll, hasActiveState: hasActiveState, extra: _jsxs(Label, { layout: "flex", gap: "xs", className: "cursor-pointer select-none shrink-0", children: [_jsx(Span, { size: "xs", className: "hidden sm:inline whitespace-nowrap", color: "muted", children: "Show closed" }), _jsx("button", { type: "button", role: "switch", "aria-checked": showClosed, onClick: () => table.set("showClosed", showClosed ? "" : "true"), className: `relative inline-flex h-5 w-9 flex-shrink-0 items-center rounded-full transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-1 ${showClosed ? "bg-primary" : "bg-zinc-300 dark:bg-slate-600"}`, children: _jsx(Span, { className: `inline-block h-3.5 w-3.5 transform transition-transform duration-200 ${showClosed ? "translate-x-[19px]" : "translate-x-[3px]"}`, rounded: "full", surface: "default", shadow: "sm" }) })] }) }), totalPages > 1 && (_jsx(Row, { border: "bottom", className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 backdrop-blur-sm", surface: "default", padding: "toolbar", justify: "center", children: _jsx(Pagination, { currentPage: page, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsx(Div, { padding: "y-lg", children: isLoading ? (_jsx(Div, { className: gridClass, children: Array.from({ length: 8 }).map((_, i) => (_jsxs(Div, { className: "overflow-hidden animate-pulse", border: "subtle", rounded: "xl", children: [_jsx(Div, { className: "aspect-square", surface: "subtle" }), _jsxs(Stack, { className: `${__P.p3}`, gap: "sm", children: [_jsx(Div, { className: "h-3 w-3/4", surface: "subtle", rounded: "default" }), _jsx(Div, { className: "h-3 w-1/2", surface: "subtle", rounded: "default" }), _jsx(Div, { className: "h-8", surface: "subtle", rounded: "default" })] })] }, i))) })) : filteredDraws.length === 0 ? (_jsx(Text, { paddingY: "3xl", color: "muted", size: "sm", align: "center", children: "No prize draws found." })) : (_jsx(Div, { className: gridClass, children: filteredDraws.map((product) => (_jsx(MarketplacePrizeDrawCard, { product: product, variant: view }, product.id))) })) }), _jsx(FilterDrawer, { open: filterOpen, onOpen: openFilters, onClose: () => setFilterOpen(false), onApply: applyFilters, onReset: onFilterClear, activeCount: filterActiveCount, hideTrigger: true, children: _jsxs(Stack, { gap: "md", children: [_jsxs(_Fragment, { children: [_jsx("label", { htmlFor: "prizeRevealStatusFilter", className: "block text-xs font-semibold text-[var(--appkit-color-text-muted)] mb-1.5", children: "Reveal status" }), _jsxs("select", { id: "prizeRevealStatusFilter", value: pendingTable.get(TABLE_KEYS.PRIZE_REVEAL_STATUS) ?? "", onChange: (e) => pendingTable.set(TABLE_KEYS.PRIZE_REVEAL_STATUS, e.target.value), className: "w-full rounded border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-2 py-1.5 text-sm", children: [_jsx("option", { value: "", children: "Any" }), _jsx("option", { value: "pending", children: "Reveal pending" }), _jsx("option", { value: "open", children: "Reveal open" }), _jsx("option", { value: "closed", children: "Closed" })] })] }), _jsx(ProductFilters, { table: pendingTable, currencyPrefix: "\u20B9", categoryOptions: categoryOptions, brandOptions: brandOptions })] }) })] }));
89
+ }, onResetAll: resetAll, hasActiveState: hasActiveState, toggles: [
90
+ { label: "Show closed", active: showClosed, onChange: (next) => table.set(TABLE_KEYS.SHOW_CLOSED, next ? "true" : "") },
91
+ ] }), totalPages > 1 && (_jsx(Row, { border: "bottom", className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 backdrop-blur-sm", surface: "default", padding: "toolbar", justify: "center", children: _jsx(Pagination, { currentPage: page, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsx(Div, { padding: "y-lg", children: isLoading ? (_jsx(Div, { className: gridClass, children: Array.from({ length: 8 }).map((_, i) => (_jsxs(Div, { className: "overflow-hidden animate-pulse", border: "subtle", rounded: "xl", children: [_jsx(Div, { className: "aspect-square", surface: "subtle" }), _jsxs(Stack, { className: `${__P.p3}`, gap: "sm", children: [_jsx(Div, { className: "h-3 w-3/4", surface: "subtle", rounded: "default" }), _jsx(Div, { className: "h-3 w-1/2", surface: "subtle", rounded: "default" }), _jsx(Div, { className: "h-8", surface: "subtle", rounded: "default" })] })] }, i))) })) : filteredDraws.length === 0 ? (_jsx(Text, { paddingY: "3xl", color: "muted", size: "sm", align: "start", children: "No prize draws found." })) : (_jsx(Div, { className: gridClass, children: filteredDraws.map((product) => (_jsx(MarketplacePrizeDrawCard, { product: product, variant: view }, product.id))) })) }), _jsx(FilterDrawer, { open: filterOpen, onOpen: openFilters, onClose: () => setFilterOpen(false), onApply: applyFilters, onReset: onFilterClear, activeCount: filterActiveCount, hideTrigger: true, children: _jsxs(Stack, { gap: "md", children: [_jsxs(_Fragment, { children: [_jsx(Label, { htmlFor: "prizeRevealStatusFilter", size: "xs", weight: "semibold", color: "muted", className: "block mb-1.5", children: "Reveal status" }), _jsx(Select, { id: "prizeRevealStatusFilter", options: [
92
+ { value: "", label: "Any" },
93
+ { value: "pending", label: "Reveal pending" },
94
+ { value: "open", label: "Reveal open" },
95
+ { value: "closed", label: "Closed" },
96
+ ], value: pendingTable.get(TABLE_KEYS.PRIZE_REVEAL_STATUS) ?? "", onValueChange: (v) => pendingTable.set(TABLE_KEYS.PRIZE_REVEAL_STATUS, v) })] }), _jsx(ProductFilters, { table: pendingTable, currencyPrefix: "\u20B9", categoryOptions: categoryOptions, brandOptions: brandOptions })] }) })] }));
90
97
  }
@@ -28,5 +28,5 @@ export async function PrizeDrawsSection({ config, }) {
28
28
  void normalizeError(_err);
29
29
  draws = [];
30
30
  }
31
- return (_jsx(Section, { padding: "y-2xl", children: _jsx(Container, { size: "xl", children: _jsxs(Stack, { gap: "md", children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 2, size: "2xl", weight: "semibold", color: "primary", children: title }), subtitle ? (_jsx(Text, { size: "sm", color: "muted", children: subtitle })) : null] }), draws.length === 0 ? (_jsxs(Stack, { align: "center", gap: "sm", className: "border-dashed text-center", border: "strong", paddingY: "y-3xl", paddingX: "x-lg", rounded: "2xl", children: [_jsx(Text, { size: "sm", color: "muted", children: "No active prize draws \u2014 new draws are announced regularly." }), _jsx(Link, { href: String(ROUTES.PUBLIC.AUCTIONS), className: "text-sm font-medium text-primary hover:underline", children: "Browse live auctions \u2192" })] })) : (_jsx(Div, { gap: "3", className: "fluid-grid-card", children: draws.map((draw) => (_jsx(InteractiveProductCard, { product: draw, href: String(ROUTES.PUBLIC.PRODUCT_DETAIL(draw.slug ?? draw.id ?? "")) }, draw.id))) }))] }) }) }));
31
+ return (_jsx(Section, { padding: "y-2xl", children: _jsx(Container, { size: "xl", children: _jsxs(Stack, { gap: "md", children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 2, size: "2xl", weight: "semibold", color: "primary", children: title }), subtitle ? (_jsx(Text, { size: "sm", color: "muted", children: subtitle })) : null] }), draws.length === 0 ? (_jsxs(Stack, { align: "start", gap: "sm", className: "border-dashed text-left", border: "strong", paddingY: "y-3xl", paddingX: "x-lg", rounded: "2xl", children: [_jsx(Text, { size: "sm", color: "muted", children: "No active prize draws \u2014 new draws are announced regularly." }), _jsx(Link, { href: String(ROUTES.PUBLIC.AUCTIONS), className: "text-[length:var(--appkit-text-sm)] font-medium text-primary hover:underline", children: "Browse live auctions \u2192" })] })) : (_jsx(Div, { gap: "3", className: "fluid-grid-card", children: draws.map((draw) => (_jsx(InteractiveProductCard, { product: draw, href: String(ROUTES.PUBLIC.PRODUCT_DETAIL(draw.slug ?? draw.id ?? "")) }, draw.id))) }))] }) }) }));
32
32
  }
@@ -19,11 +19,12 @@ import { Anchor, Button, Div, Heading, LoginRequiredModal, Modal, Span, Stack, T
19
19
  import { MediaImage } from "../../media/MediaImage";
20
20
  import { isAuthError } from "../../../utils/auth-error";
21
21
  import { PrizeDrawCollage } from "./PrizeDrawCollage";
22
+ import { PRIZE_DRAW_ENDPOINTS } from "../../../constants/api-endpoints";
22
23
  import { normalizeError } from "../../../errors/normalize";
23
24
  const __P = {
24
- p4: "p-4",
25
+ p4: "p-[var(--appkit-space-4)]",
25
26
  };
26
- const CLS_REFUND_NOTE = "rounded border border-warning/40 bg-warning-surface px-4 py-3 text-warning dark:bg-warning-surface dark:text-warning";
27
+ const CLS_REFUND_NOTE = "rounded border border-warning/40 bg-warning-surface px-[var(--appkit-space-4)] py-[var(--appkit-space-3)] text-warning dark:bg-warning-surface dark:text-warning";
27
28
  const REVEAL_DURATION_MS = 3200; // total animation length
28
29
  const CYCLE_INTERVAL_FAST = 80;
29
30
  const CYCLE_INTERVAL_SLOW = 360;
@@ -31,7 +32,7 @@ function isUnauthenticatedResponse(status) {
31
32
  return status === 401 || status === 403;
32
33
  }
33
34
  async function fetchPrizeReveal(productId, orderId) {
34
- const res = await fetch(`/api/prize-draws/${productId}/reveal`, {
35
+ const res = await fetch(PRIZE_DRAW_ENDPOINTS.REVEAL(productId), {
35
36
  method: "POST",
36
37
  headers: { "Content-Type": "application/json" },
37
38
  body: JSON.stringify({ orderId }),
@@ -150,6 +151,10 @@ export function PrizeRevealModal({ open, onClose, items, orderId, productId, onR
150
151
  }, REVEAL_DURATION_MS);
151
152
  }, [onReveal, orderId, phase, productId, startAnimation]);
152
153
  const winnerImg = winner?.images?.[0];
153
- return (_jsxs(Modal, { isOpen: open, onClose: onClose, title: "Prize Reveal", size: "lg", children: [_jsx(LoginRequiredModal, { isOpen: showLoginModal, onClose: () => setShowLoginModal(false), message: "You need to be signed in to reveal your prize. Please log in or create an account to continue." }), _jsxs(Stack, { gap: "md", children: [phase === "refunded" ? (_jsxs(Div, { className: CLS_REFUND_NOTE, children: [_jsx(Heading, { level: 3, className: "mb-1", children: "Pool exhausted \u2014 you've been refunded" }), _jsx(Text, { size: "sm", children: "Every prize in this draw was already claimed by the time your entry rolled. Your order has been marked refunded automatically." })] })) : null, phase === "error" ? (_jsxs(Div, { className: "border border-error/40", color: "error", surface: "danger-surface", padding: "inline", rounded: "default", children: [_jsx(Text, { size: "sm", weight: "semibold", children: "Something went wrong" }), _jsx(Text, { size: "sm", children: errorMessage })] })) : null, _jsx(PrizeDrawCollage, { items: items, hideWonState: true, highlightItemNumber: highlight }), phase === "idle" ? (_jsx(Button, { type: "button", variant: "primary", size: "lg", onClick: handleRevealClick, children: "\u2728 Reveal my prize" })) : null, phase === "revealing" ? (_jsxs(Div, { className: `bg-[var(--appkit-color-surface-muted)] ${__P.p4} text-center`, rounded: "default", children: [_jsx(Text, { size: "lg", weight: "semibold", children: "Rolling\u2026" }), _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "The winner was locked by the server before this animation started. Hang tight \u2014 we're just making it look pretty." })] })) : null, phase === "won" && winner ? (_jsxs(Div, { className: `border-2 border-[var(--appkit-color-primary)] bg-[var(--appkit-color-surface)] ${__P.p4} text-center`, rounded: "lg", children: [_jsx(Text, { className: "tracking-wider text-[var(--appkit-color-text-muted)]", size: "xs", transform: "uppercase", children: "You won" }), _jsxs(Heading, { level: 2, className: "my-2", children: ["#", winner.itemNumber, " \u2014 ", winner.title] }), winnerImg ? (_jsx(Div, { className: "relative mx-auto h-64 w-64 max-w-full", rounded: "md", overflow: "hidden", children: _jsx(MediaImage, { src: winnerImg, alt: winner.title, size: "hero", objectFit: "contain" }) })) : null, winner.estimatedValue != null ? (_jsxs(Text, { className: "mt-2 text-[var(--appkit-color-text-muted)]", size: "sm", children: ["Estimated value: \u20B9", (winner.estimatedValue / 100).toLocaleString("en-IN")] })) : null] })) : null, _jsxs(Div, { textSize: "xs", className: "border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-muted)] text-[var(--appkit-color-text-muted)]", padding: "inlineSm", rounded: "default", children: [_jsx(Span, { weight: "bold", children: "Fairness guarantee:" }), " ", "Winners are picked by ", _jsx("code", { children: "crypto.randomInt" }), " running on LetItRip's server before the animation starts. The animation is theatrical \u2014 neither the store nor LetItRip staff can influence the outcome.", " ", effectiveRngUrl ? (_jsx(Anchor, { href: effectiveRngUrl, tone: "none", underline: "always", children: "View RNG source code \u2192" })) : null] })] })] }));
154
+ return (_jsxs(Modal, { isOpen: open, onClose: onClose, title: "Prize Reveal", size: "lg", children: [_jsx(LoginRequiredModal, { isOpen: showLoginModal, onClose: () => setShowLoginModal(false), message: "You need to be signed in to reveal your prize. Please log in or create an account to continue." }), _jsxs(Stack, { gap: "md", children: [phase === "refunded" ? (_jsxs(Div, { className: CLS_REFUND_NOTE, children: [_jsx(Heading, { level: 3, className: "mb-1", children: "Pool exhausted \u2014 you've been refunded" }), _jsx(Text, { size: "sm", children: "Every prize in this draw was already claimed by the time your entry rolled. Your order has been marked refunded automatically." })] })) : null, phase === "error" ? (_jsxs(Div, { className: "border border-error/40", color: "error", surface: "danger-surface", padding: "inline", rounded: "default", children: [_jsx(Text, { size: "sm", weight: "semibold", children: "Something went wrong" }), _jsx(Text, { size: "sm", children: errorMessage })] })) : null, _jsx(PrizeDrawCollage, { items: items, hideWonState: true, highlightItemNumber: highlight }), phase === "idle" ? (_jsx(Button, { type: "button", variant: "primary", size: "lg", onClick: handleRevealClick, children: "\u2728 Reveal my prize" })) : null, phase === "revealing" ? (
155
+ // audit-content-alignment-ok: theatrical reveal-modal centerpiece, not marketing content
156
+ _jsxs(Div, { className: `bg-[var(--appkit-color-surface-muted)] ${__P.p4} text-center`, rounded: "default", children: [_jsx(Text, { size: "lg", weight: "semibold", children: "Rolling\u2026" }), _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "The winner was locked by the server before this animation started. Hang tight \u2014 we're just making it look pretty." })] })) : null, phase === "won" && winner ? (
157
+ // audit-content-alignment-ok: theatrical reveal-modal centerpiece, not marketing content
158
+ _jsxs(Div, { className: `border-2 border-[var(--appkit-color-primary)] bg-[var(--appkit-color-surface)] ${__P.p4} text-center`, rounded: "lg", children: [_jsx(Text, { className: "tracking-wider text-[var(--appkit-color-text-muted)]", size: "xs", transform: "uppercase", children: "You won" }), _jsxs(Heading, { level: 2, className: "my-2", children: ["#", winner.itemNumber, " \u2014 ", winner.title] }), winnerImg ? (_jsx(Div, { className: "relative mx-auto h-64 w-64 max-w-full", rounded: "md", overflow: "hidden", children: _jsx(MediaImage, { src: winnerImg, alt: winner.title, size: "hero", objectFit: "contain" }) })) : null, winner.estimatedValue != null ? (_jsxs(Text, { className: "mt-2 text-[var(--appkit-color-text-muted)]", size: "sm", children: ["Estimated value: \u20B9", (winner.estimatedValue / 100).toLocaleString("en-IN")] })) : null] })) : null, _jsxs(Div, { textSize: "xs", className: "border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-muted)] text-[var(--appkit-color-text-muted)]", padding: "inlineSm", rounded: "default", children: [_jsx(Span, { weight: "bold", children: "Fairness guarantee:" }), " ", "Winners are picked by ", _jsx("code", { children: "crypto.randomInt" }), " running on LetItRip's server before the animation starts. The animation is theatrical \u2014 neither the store nor LetItRip staff can influence the outcome.", " ", effectiveRngUrl ? (_jsx(Anchor, { href: effectiveRngUrl, tone: "none", underline: "always", children: "View RNG source code \u2192" })) : null] })] })] }));
154
159
  }
155
160
  export default PrizeRevealModal;
@@ -6,6 +6,7 @@ import { Button, Stack, LoginRequiredModal } from "../../../ui";
6
6
  import { useToast } from "../../../ui/components/Toast";
7
7
  import { useAddToCart } from "../../cart/hooks/useAddToCart";
8
8
  import { apiClient } from "../../../http";
9
+ import { WISHLIST_ENDPOINTS } from "../../../constants/api-endpoints";
9
10
  import { addToGuestWishlist } from "../../wishlist/utils/guest-wishlist";
10
11
  import { ROUTES } from "../../../next";
11
12
  import { useAuthGate } from "../../../react/hooks/useAuthGate";
@@ -57,7 +58,7 @@ export function ProductDetailActions({ productId, productSlug: _productSlug, pro
57
58
  setBusy("wish");
58
59
  try {
59
60
  try {
60
- await apiClient.post("/api/wishlist", { productId });
61
+ await apiClient.post(WISHLIST_ENDPOINTS.ADD, { productId });
61
62
  }
62
63
  catch (err) {
63
64
  void normalizeError(err);
@@ -2,25 +2,25 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import Link from "next/link";
3
3
  import { productRepository, reviewRepository } from "../../../repositories";
4
4
  const __P = {
5
- p3: "p-3",
6
- p5: "p-5",
5
+ p3: "p-[var(--appkit-space-3)]",
6
+ p5: "p-[var(--appkit-space-5)]",
7
7
  };
8
8
  const CLS_BREADCRUMB_LINK = "hover:text-primary-600 transition-colors";
9
9
  const ACTION_NOT_WIRED = "Action not wired";
10
- const CLS_STAR_FULL = "text-warning text-sm";
11
- const CLS_STAR_HALF = "text-warning text-sm";
12
- const CLS_STAR_EMPTY = "text-[var(--appkit-color-text-faint)] text-sm";
10
+ const CLS_STAR_FULL = "text-warning text-[length:var(--appkit-text-sm)]";
11
+ const CLS_STAR_HALF = "text-warning text-[length:var(--appkit-text-sm)]";
12
+ const CLS_STAR_EMPTY = "text-[var(--appkit-color-text-faint)] text-[length:var(--appkit-text-sm)]";
13
13
  const CLS_STOCK_IN = "bg-success-surface text-success dark:bg-success-surface dark:text-success";
14
14
  const CLS_STOCK_OUT = "bg-error-surface text-error dark:bg-error-surface dark:text-error";
15
- const CLS_BUNDLE_PILL = "inline-flex items-center gap-1 rounded-full border border-success bg-success-surface px-2.5 py-1 text-xs font-semibold text-success transition-colors hover:border-success hover:bg-success-surface dark:border-success/60 dark:bg-success-surface dark:text-success dark:hover:border-success dark:hover:bg-success-surface";
16
- const CLS_DISCOUNT_BADGE = "rounded-full bg-error-surface px-2 py-0.5 text-white";
15
+ const CLS_BUNDLE_PILL = "inline-flex items-center gap-[var(--appkit-space-1)] rounded-full border border-success bg-success-surface px-[var(--appkit-space-2-5)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] font-semibold text-success transition-colors hover:border-success hover:bg-success-surface dark:border-success/60 dark:bg-success-surface dark:text-success dark:hover:border-success dark:hover:bg-success-surface";
16
+ const CLS_DISCOUNT_BADGE = "rounded-full bg-error-surface px-[var(--appkit-space-2)] py-[var(--appkit-space-0-5)] text-white";
17
17
  const CLS_FREE_SHIPPING_ICON = "mt-0.5 flex-shrink-0 text-success";
18
- const CLS_BUNDLE_BOX = "rounded-xl border border-success dark:border-success/60 bg-success-surface dark:bg-success-surface p-5";
18
+ const CLS_BUNDLE_BOX = "rounded-xl border border-success dark:border-success/60 bg-success-surface dark:bg-success-surface p-[var(--appkit-space-5)]";
19
19
  const CLS_BUNDLE_ICON = "text-success dark:text-success";
20
- const CLS_BUNDLE_TITLE = "text-sm font-semibold text-success dark:text-success";
21
- const CLS_BUNDLE_ROW = "flex items-center justify-between gap-4 rounded-lg border border-success dark:border-success/50 bg-white dark:bg-success-surface px-4 py-3";
22
- const CLS_BUNDLE_LABEL = "text-xs text-success dark:text-success font-medium uppercase tracking-wide mb-0.5";
23
- const CLS_BUNDLE_CTA = "flex-shrink-0 rounded-lg bg-success-surface hover:bg-success-surface px-3 py-1.5 text-xs font-semibold text-white transition-colors";
20
+ const CLS_BUNDLE_TITLE = "text-[length:var(--appkit-text-sm)] font-semibold text-success dark:text-success";
21
+ const CLS_BUNDLE_ROW = "flex items-center justify-between gap-[var(--appkit-space-4)] rounded-lg border border-success dark:border-success/50 bg-white dark:bg-success-surface px-[var(--appkit-space-4)] py-[var(--appkit-space-3)]";
22
+ const CLS_BUNDLE_LABEL = "text-[length:var(--appkit-text-xs)] text-success dark:text-success font-medium uppercase tracking-wide mb-0.5";
23
+ const CLS_BUNDLE_CTA = "flex-shrink-0 rounded-lg bg-success-surface hover:bg-success-surface px-[var(--appkit-space-3)] py-[var(--appkit-space-1-5)] text-[length:var(--appkit-text-xs)] font-semibold text-white transition-colors";
24
24
  import { ROUTES } from "../../../next";
25
25
  import { getDefaultCurrency } from "../../../core/baseline-resolver";
26
26
  import { Button, Container, Div, Heading, Main, Nav, RichText, Row, Section, Span, Stack, Text, Ul, Ol, Li, Dl, Dt, Dd, } from "../../../ui";
@@ -114,7 +114,7 @@ export async function ProductDetailPageView({ slug, initialProduct, renderOfferA
114
114
  ? (initialProduct ?? undefined)
115
115
  : await productRepository.findByIdOrSlug(slug).catch(() => undefined);
116
116
  if (!product) {
117
- return (_jsx(Main, { children: _jsx(Section, { padding: "y-5xl", children: _jsx(Container, { size: "md", children: _jsxs(Stack, { align: "center", gap: "md", className: "text-center", children: [_jsx(Heading, { level: 1, size: "2xl", weight: "semibold", color: "primary", children: "Product Not Found" }), _jsx(Text, { color: "muted", children: "The product you are looking for may have been removed or the link is incorrect." }), _jsx(Link, { href: String(ROUTES.PUBLIC.PRODUCTS), className: "text-sm font-medium text-primary-600 hover:underline", children: "Browse Products" })] }) }) }) }));
117
+ return (_jsx(Main, { children: _jsx(Section, { padding: "y-5xl", children: _jsx(Container, { size: "md", children: _jsxs(Stack, { align: "start", gap: "md", className: "text-left", children: [_jsx(Heading, { level: 1, size: "2xl", weight: "semibold", color: "primary", children: "Product Not Found" }), _jsx(Text, { color: "muted", children: "The product you are looking for may have been removed or the link is incorrect." }), _jsx(Link, { href: String(ROUTES.PUBLIC.PRODUCTS), className: "text-[length:var(--appkit-text-sm)] font-medium text-primary-600 hover:underline", children: "Browse Products" })] }) }) }) }));
118
118
  }
119
119
  const p = product;
120
120
  const currency = p.currency || getDefaultCurrency();
@@ -262,7 +262,7 @@ export async function ProductDetailPageView({ slug, initialProduct, renderOfferA
262
262
  ? ` — only ${effectiveStock} left`
263
263
  : ""] })] })) : (_jsxs(Span, { layout: "inline-flex", gap: "xs", className: `w-fit .5 ${inStock ? CLS_STOCK_IN : CLS_STOCK_OUT}`, rounded: "full", padding: "pill-md", size: "xs", weight: "medium", children: [inStock ? "✓ In Stock" : "✗ Out of Stock", inStock && effectiveStock !== null && effectiveStock <= 10
264
264
  ? ` — only ${effectiveStock} left`
265
- : ""] })), (categorySlugs.length > 0 || subcategory || brand) && (_jsxs(Row, { gap: "sm", wrap: true, children: [categorySlugs.map((slug, i) => (_jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(slug)), className: "inline-flex items-center rounded-full border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-2.5 py-1 text-xs font-medium text-[var(--appkit-color-text-muted)] transition-colors hover:border-primary-300 hover:bg-primary-50 hover:text-primary-700 dark:hover:border-primary-700/60 dark:hover:bg-primary-900/20 dark:hover:text-primary-400", children: categoryNames[i] ?? slug }, slug))), subcategory && (_jsx(Span, { layout: "inline-flex", size: "xs", weight: "medium", border: "subtle", rounded: "full", padding: "pill-sm-tall", surface: "muted", color: "muted", transform: "capitalize", children: subcategory })), brand && brandSlug && (_jsx(Link, { href: String(ROUTES.PUBLIC.BRAND_DETAIL(brandSlug)), className: "inline-flex items-center rounded-full border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-2.5 py-1 text-xs font-medium text-[var(--appkit-color-text-muted)] transition-colors hover:border-primary-300 hover:bg-primary-50 hover:text-primary-700 dark:hover:border-primary-700/60 dark:hover:bg-primary-900/20 dark:hover:text-primary-400", children: brand })), brand && !brandSlug && (_jsx(Span, { layout: "inline-flex", size: "xs", weight: "medium", border: "subtle", rounded: "full", padding: "pill-sm-tall", surface: "muted", color: "muted", children: brand }))] })), bundleMemberships.length > 0 && (_jsx(Row, { gap: "sm", wrap: true, children: bundleMemberships.map((b) => (_jsxs(Link, { href: String(ROUTES.PUBLIC.BUNDLE_DETAIL(b.id)), className: CLS_BUNDLE_PILL, children: [_jsx(Span, { "aria-hidden": "true", children: "\uD83D\uDCE6" }), "In bundle: ", b.title] }, b.id))) })), _jsx(ProductFeatureBadges, { featured: featured, freeShipping: freeShipping, codAvailable: codEnabled === true, codHref: String(ROUTES.PUBLIC.HOW_CHECKOUT_WORKS), emiAvailable: emiEnabled === true, emiHref: String(ROUTES.PUBLIC.HOW_EMI_WORKS), condition: condition ?? undefined, returnable: returnPolicy != null && returnPolicy.length > 0, labels: {
265
+ : ""] })), (categorySlugs.length > 0 || subcategory || brand) && (_jsxs(Row, { gap: "sm", wrap: true, children: [categorySlugs.map((slug, i) => (_jsx(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(slug)), className: "inline-flex items-center rounded-full border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-[var(--appkit-space-2-5)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] font-medium text-[var(--appkit-color-text-muted)] transition-colors hover:border-primary-300 hover:bg-primary-50 hover:text-primary-700 dark:hover:border-primary-700/60 dark:hover:bg-primary-900/20 dark:hover:text-primary-400", children: categoryNames[i] ?? slug }, slug))), subcategory && (_jsx(Span, { layout: "inline-flex", size: "xs", weight: "medium", border: "subtle", rounded: "full", padding: "pill-sm-tall", surface: "muted", color: "muted", transform: "capitalize", children: subcategory })), brand && brandSlug && (_jsx(Link, { href: String(ROUTES.PUBLIC.BRAND_DETAIL(brandSlug)), className: "inline-flex items-center rounded-full border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-[var(--appkit-space-2-5)] py-[var(--appkit-space-1)] text-[length:var(--appkit-text-xs)] font-medium text-[var(--appkit-color-text-muted)] transition-colors hover:border-primary-300 hover:bg-primary-50 hover:text-primary-700 dark:hover:border-primary-700/60 dark:hover:bg-primary-900/20 dark:hover:text-primary-400", children: brand })), brand && !brandSlug && (_jsx(Span, { layout: "inline-flex", size: "xs", weight: "medium", border: "subtle", rounded: "full", padding: "pill-sm-tall", surface: "muted", color: "muted", children: brand }))] })), bundleMemberships.length > 0 && (_jsx(Row, { gap: "sm", wrap: true, children: bundleMemberships.map((b) => (_jsxs(Link, { href: String(ROUTES.PUBLIC.BUNDLE_DETAIL(b.id)), className: CLS_BUNDLE_PILL, children: [_jsx(Span, { "aria-hidden": "true", children: "\uD83D\uDCE6" }), "In bundle: ", b.title] }, b.id))) })), _jsx(ProductFeatureBadges, { featured: featured, freeShipping: freeShipping, codAvailable: codEnabled === true, codHref: String(ROUTES.PUBLIC.HOW_CHECKOUT_WORKS), emiAvailable: emiEnabled === true, emiHref: String(ROUTES.PUBLIC.HOW_EMI_WORKS), condition: condition ?? undefined, returnable: returnPolicy != null && returnPolicy.length > 0, labels: {
266
266
  featured: "Featured",
267
267
  fasterDelivery: "Faster Delivery",
268
268
  ratedSeller: "Rated Seller",
@@ -277,9 +277,9 @@ export async function ProductDetailPageView({ slug, initialProduct, renderOfferA
277
277
  emiAvailable: "EMI Available",
278
278
  wishlistCount: (n) => `${n} wishlisted`,
279
279
  categoryProductCount: (n, cat) => `${n} in ${cat}`,
280
- } }), productFeatures && features.length > 0 && (_jsx(FeatureBadgeList, { productFeatureIds: features, features: productFeatures })), !productFeatures && features.length > 0 && (_jsxs(Div, { border: "subtle", surface: "muted", padding: "inline", rounded: "xl", children: [_jsx(Text, { className: "mb-2 tracking-wide", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: "About this product" }), _jsx(Ul, { spacing: "comfortable", size: "sm", color: "primary", children: features.map((f, i) => (_jsxs(Li, { layout: "flex-start", gap: "2", children: [_jsx(Span, { className: "mt-0.5 flex-shrink-0 text-primary-500", children: "\u2022" }), f] }, i))) })] })), descriptionHtml && (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-sm leading-relaxed text-[var(--appkit-color-text-muted)] line-clamp-4" })), safeSeller && (_jsx(Div, { className: `${__P.p3}`, border: "subtle", rounded: "xl", surface: "muted", children: _jsxs(Row, { justify: "between", align: "center", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-[10px] tracking-wide mb-0.5", color: "faint", transform: "uppercase", children: "Sold by" }), _jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: safeSeller }), typeof p.storeRating === "number" && p.storeRating > 0 && (_jsx(Row, { gap: "xs", align: "center", className: "mt-0.5", children: _jsxs(Text, { size: "xs", color: "muted", children: [_jsx(Span, { className: "text-warning", "aria-hidden": "true", children: "\u2605" }), " ", p.storeRating.toFixed(1), typeof p.storeReviewCount === "number" &&
280
+ } }), productFeatures && features.length > 0 && (_jsx(FeatureBadgeList, { productFeatureIds: features, features: productFeatures })), !productFeatures && features.length > 0 && (_jsxs(Div, { border: "subtle", surface: "muted", padding: "inline", rounded: "xl", children: [_jsx(Text, { className: "mb-2 tracking-wide", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: "About this product" }), _jsx(Ul, { spacing: "comfortable", size: "sm", color: "primary", children: features.map((f, i) => (_jsxs(Li, { layout: "flex-start", gap: "2", children: [_jsx(Span, { className: "mt-0.5 flex-shrink-0 text-primary-500", children: "\u2022" }), f] }, i))) })] })), descriptionHtml && (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-[length:var(--appkit-text-sm)] leading-relaxed text-[var(--appkit-color-text-muted)] line-clamp-4" })), safeSeller && (_jsx(Div, { className: `${__P.p3}`, border: "subtle", rounded: "xl", surface: "muted", children: _jsxs(Row, { justify: "between", align: "center", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-[10px] tracking-wide mb-0.5", color: "faint", transform: "uppercase", children: "Sold by" }), _jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: safeSeller }), typeof p.storeRating === "number" && p.storeRating > 0 && (_jsx(Row, { gap: "xs", align: "center", className: "mt-0.5", children: _jsxs(Text, { size: "xs", color: "muted", children: [_jsx(Span, { className: "text-warning", "aria-hidden": "true", children: "\u2605" }), " ", p.storeRating.toFixed(1), typeof p.storeReviewCount === "number" &&
281
281
  p.storeReviewCount > 0 &&
282
- ` · ${p.storeReviewCount} reviews`] }) }))] }), storeHref && (_jsx(Link, { href: storeHref, className: "shrink-0 rounded-lg bg-primary/10 dark:bg-primary/20 px-3 py-1.5 text-xs font-semibold text-primary-700 dark:text-primary-300 hover:bg-primary/20 dark:hover:bg-primary/30 transition-colors", children: "Visit Store \u2192" }))] }) }))] })), renderActions: () => (_jsxs(Stack, { className: `${__P.p5}`, border: "subtle", gap: "md", rounded: "xl", surface: "muted", children: [formattedPrice && (_jsxs(Div, { children: [_jsxs(Row, { align: "baseline", gap: "sm", wrap: true, children: [_jsx(Text, { size: "2xl", weight: "bold", color: "primary", children: formattedPrice }), formattedOriginal && discount && (_jsxs(_Fragment, { children: [_jsx(Span, { size: "sm", className: "line-through", color: "faint", children: formattedOriginal }), _jsxs(Span, { size: "xs", weight: "bold", className: CLS_DISCOUNT_BADGE, children: ["-", discount, "%"] })] }))] }), inStock && effectiveStock !== null && effectiveStock <= 10 && (_jsxs(Text, { className: "mt-1 text-warning", size: "xs", children: ["Only ", effectiveStock, " left \u2014 order soon!"] }))] })), _jsxs(Stack, { gap: "sm", children: [renderPrimaryActions ? (renderPrimaryActions({
282
+ ` · ${p.storeReviewCount} reviews`] }) }))] }), storeHref && (_jsx(Link, { href: storeHref, className: "shrink-0 rounded-lg bg-primary/10 dark:bg-primary/20 px-[var(--appkit-space-3)] py-[var(--appkit-space-1-5)] text-[length:var(--appkit-text-xs)] font-semibold text-primary-700 dark:text-primary-300 hover:bg-primary/20 dark:hover:bg-primary/30 transition-colors", children: "Visit Store \u2192" }))] }) }))] })), renderActions: () => (_jsxs(Stack, { className: `${__P.p5}`, border: "subtle", gap: "md", rounded: "xl", surface: "muted", children: [formattedPrice && (_jsxs(Div, { children: [_jsxs(Row, { align: "baseline", gap: "sm", wrap: true, children: [_jsx(Text, { size: "2xl", weight: "bold", color: "primary", children: formattedPrice }), formattedOriginal && discount && (_jsxs(_Fragment, { children: [_jsx(Span, { size: "sm", className: "line-through", color: "faint", children: formattedOriginal }), _jsxs(Span, { size: "xs", weight: "bold", className: CLS_DISCOUNT_BADGE, children: ["-", discount, "%"] })] }))] }), inStock && effectiveStock !== null && effectiveStock <= 10 && (_jsxs(Text, { className: "mt-1 text-warning", size: "xs", children: ["Only ", effectiveStock, " left \u2014 order soon!"] }))] })), _jsxs(Stack, { gap: "sm", children: [renderPrimaryActions ? (renderPrimaryActions({
283
283
  productId: product.id,
284
284
  productSlug: product.slug ?? slug,
285
285
  productTitle: product.title,
@@ -2,18 +2,18 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import React from "react";
4
4
  import { useQuery } from "@tanstack/react-query";
5
- import { Div, Grid, Heading, Label, Stack, Text } from "../../../ui";
5
+ import { Checkbox, Div, Grid, Heading, Label, Stack, Text } from "../../../ui";
6
6
  import { apiClient } from "../../../http";
7
7
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
8
8
  import { PRODUCT_FEATURE_QUERY_STALE_MS } from "../constants/product-features.constants";
9
9
  import { MAX_FEATURES_PER_PRODUCT, } from "../schemas/product-features";
10
10
  const SECTION_LABEL_CLASS = "text-[var(--appkit-font-size-2xs,11px)] font-semibold uppercase tracking-wide text-[var(--appkit-color-text-muted)] mb-2";
11
- const ROW_BASE_CLASS = "flex items-start gap-2 rounded-lg border px-3 py-2 text-xs cursor-pointer transition-colors";
11
+ const ROW_BASE_CLASS = "flex items-start gap-[var(--appkit-space-2)] rounded-lg border px-[var(--appkit-space-3)] py-[var(--appkit-space-2)] text-[length:var(--appkit-text-xs)] cursor-pointer transition-colors";
12
12
  const ROW_CHECKED_CLASS = "border-primary bg-primary/5 dark:bg-primary/10";
13
13
  const ROW_DISABLED_CLASS = "border-[var(--appkit-color-border)] opacity-50 cursor-not-allowed";
14
14
  const ROW_DEFAULT_CLASS = "border-[var(--appkit-color-border)] hover:bg-zinc-50 hover:bg-[var(--appkit-color-surface-elevated)]";
15
- const OVER_LIMIT_BANNER_CLASS = "rounded-lg border border-error/20 bg-error-surface px-3 py-2 text-xs text-error";
16
- const EMPTY_STATE_CLASS = "rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-3 py-4 text-xs text-[var(--appkit-color-text-muted)] text-center";
15
+ const OVER_LIMIT_BANNER_CLASS = "rounded-lg border border-error/20 bg-error-surface px-[var(--appkit-space-3)] py-[var(--appkit-space-2)] text-[length:var(--appkit-text-xs)] text-error";
16
+ const EMPTY_STATE_CLASS = "rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-[var(--appkit-space-3)] py-[var(--appkit-space-4)] text-[length:var(--appkit-text-xs)] text-[var(--appkit-color-text-muted)] text-left";
17
17
  function applyProductType(list, productType) {
18
18
  if (productType === "all")
19
19
  return list;
@@ -62,7 +62,7 @@ export function ProductFeaturesSelector({ value, onChange, productType, storeId,
62
62
  const renderRow = (f) => {
63
63
  const checked = selectedSet.has(f.id);
64
64
  const cantSelect = !checked && atLimit;
65
- return (_jsxs(Label, { className: rowClass(checked, cantSelect), children: [_jsx("input", { type: "checkbox", className: "mt-0.5", checked: checked, disabled: disabled || cantSelect, onChange: () => toggle(f.id), "aria-label": f.label }), _jsxs(Div, { className: "flex-1", children: [_jsx(Text, { as: "span", className: "block", color: "primary", weight: "medium", children: f.label }), f.description && (_jsx(Text, { as: "span", className: "block mt-0.5", color: "muted", children: f.description }))] })] }, f.id));
65
+ return (_jsxs(Label, { className: rowClass(checked, cantSelect), children: [_jsx(Checkbox, { bare: true, className: "mt-0.5", checked: checked, disabled: disabled || cantSelect, onChange: () => toggle(f.id), "aria-label": f.label }), _jsxs(Div, { className: "flex-1", children: [_jsx(Text, { as: "span", className: "block", color: "primary", weight: "medium", children: f.label }), f.description && (_jsx(Text, { as: "span", className: "block mt-0.5", color: "muted", children: f.description }))] })] }, f.id));
66
66
  };
67
67
  const hasAny = platformQuery.isLoading ||
68
68
  storeQuery.isLoading ||
@@ -83,7 +83,7 @@ export function ProductForm({ product, onChange, isReadonly = false, renderDescr
83
83
  value: (product.categorySlugs?.[0] ?? product.category) || "",
84
84
  onChange: (value) => update({ categorySlugs: value ? [value] : [] }),
85
85
  disabled: isReadonly,
86
- }) })) : (_jsx(FormField, { name: "category", label: t("formCategory"), type: "text", value: (product.categorySlugs?.[0] ?? product.category) || "", onChange: (value) => update({ categorySlugs: value ? [value] : [] }), disabled: isReadonly })), _jsx(FormField, { name: "subcategory", label: t("formSubcategory"), type: "text", value: product.subcategory || "", onChange: (value) => update({ subcategory: value }), disabled: isReadonly, placeholder: "e.g. Smartphones" })] }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", weight: "medium", color: "primary", children: t("formBrand") }), _jsx(Row, { wrap: true, gap: "3", children: ["single", "unbranded", "mixed"].map((mode) => (_jsxs(Label, { layout: "flex", gap: "xs", className: "cursor-pointer select-none", color: "primary", size: "sm", children: [_jsx("input", { type: "radio", name: "brandMode", value: mode, checked: (product.brandMode ?? "single") === mode, onChange: () => {
86
+ }) })) : (_jsx(FormField, { name: "category", label: t("formCategory"), type: "text", value: (product.categorySlugs?.[0] ?? product.category) || "", onChange: (value) => update({ categorySlugs: value ? [value] : [] }), disabled: isReadonly })), _jsx(FormField, { name: "subcategory", label: t("formSubcategory"), type: "text", value: product.subcategory || "", onChange: (value) => update({ subcategory: value }), disabled: isReadonly, placeholder: "e.g. Smartphones" })] }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", weight: "medium", color: "primary", children: t("formBrand") }), _jsx(Row, { wrap: true, gap: "3", children: ["single", "unbranded", "mixed"].map((mode) => (_jsxs(Label, { layout: "flex", gap: "xs", className: "cursor-pointer select-none", color: "primary", size: "sm", children: [_jsx(Checkbox, { bare: true, type: "radio", name: "brandMode", value: mode, checked: (product.brandMode ?? "single") === mode, onChange: () => {
87
87
  if (mode === "unbranded") {
88
88
  update({ brandMode: "unbranded", brand: undefined, brands: [] });
89
89
  }
@@ -2,7 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState } from "react";
4
4
  import { ImageLightbox } from "../../../ui/components/ImageLightbox";
5
- import { Div, Row, Stack, Text } from "../../../ui";
5
+ import { Button, Div, Row, Stack, Text } from "../../../ui";
6
6
  import { MediaImage } from "../../media/MediaImage";
7
7
  const __O = {
8
8
  hidden: "overflow-hidden",
@@ -23,7 +23,9 @@ export function ProductGalleryClient({ images, productName }) {
23
23
  return (_jsxs(Stack, { gap: "3", children: [_jsx(Div, { rounded: "xl", className: "overflow-hidden border border-[var(--appkit-color-border-subtle)] cursor-zoom-in aspect-square w-full", onClick: () => setLightboxIndex(activeIndex), role: "button", tabIndex: 0, onKeyDown: (e) => {
24
24
  if (e.key === "Enter" || e.key === " ")
25
25
  setLightboxIndex(activeIndex);
26
- }, "aria-label": `View ${productName ?? "product"} image in full screen`, children: _jsx(MediaImage, { src: mainImage, alt: productName ? `${productName} — image ${activeIndex + 1}` : `Product image ${activeIndex + 1}`, size: "gallery", className: "transition-transform duration-300 hover:scale-105" }) }), images.length > 1 && (_jsx(Div, { layout: "flex", gap: "2", className: `${__O.xAuto}`, padding: "b-2xs", children: images.map((src, i) => (_jsx("button", { type: "button", onClick: () => setActiveIndex(i), className: `flex-shrink-0 h-16 w-16 overflow-hidden rounded-lg border-2 transition-all${i === activeIndex
26
+ }, "aria-label": `View ${productName ?? "product"} image in full screen`, children: _jsx(MediaImage, { src: mainImage, alt: productName ? `${productName} — image ${activeIndex + 1}` : `Product image ${activeIndex + 1}`, size: "gallery", className: "transition-transform duration-300 hover:scale-105" }) }), images.length > 1 && (_jsx(Div, { layout: "flex", gap: "2", className: `${__O.xAuto}`, padding: "b-2xs", children: images.map((src, i) => (_jsx(Button, { variant: "ghost", type: "button", onClick: () => setActiveIndex(i), rounded: "lg", paddingX: "none", paddingY: "none", className: `flex-shrink-0 h-16 w-16 overflow-hidden border-2 transition-all${i === activeIndex
27
27
  ? " border-primary-500"
28
- : " border-transparent opacity-60 hover:opacity-100"}`, "aria-label": `View image ${i + 1}`, "aria-current": i === activeIndex ? "true" : undefined, children: _jsx(MediaImage, { src: src, alt: `Thumbnail ${i + 1}`, size: "thumbnail" }) }, i))) })), images.length > 1 && (_jsxs(Text, { size: "xs", align: "center", color: "faint", children: [activeIndex + 1, " / ", images.length] })), _jsx(ImageLightbox, { images: lightboxImages, activeIndex: lightboxIndex, onClose: () => setLightboxIndex(null), onNavigate: (i) => setLightboxIndex(i) })] }));
28
+ : " border-transparent opacity-60 hover:opacity-100"}`, "aria-label": `View image ${i + 1}`, "aria-current": i === activeIndex ? "true" : undefined, children: _jsx(MediaImage, { src: src, alt: `Thumbnail ${i + 1}`, size: "thumbnail" }) }, i))) })), images.length > 1 && (
29
+ // audit-content-alignment-ok: functional image-counter label under the gallery, not page content
30
+ _jsxs(Text, { size: "xs", align: "center", color: "faint", children: [activeIndex + 1, " / ", images.length] })), _jsx(ImageLightbox, { images: lightboxImages, activeIndex: lightboxIndex, onClose: () => setLightboxIndex(null), onNavigate: (i) => setLightboxIndex(i) })] }));
29
31
  }
@@ -14,15 +14,15 @@ import { PRODUCT_FEATURE_CARD_MAX_VISIBLE } from "../constants/product-features.
14
14
  import { normalizeListingType } from "../utils/listing-type";
15
15
  import { pluginFor } from "../../../_internal/shared/listing-types/_registry";
16
16
  const __P = {
17
- p3: "p-3",
17
+ p3: "p-[var(--appkit-space-3)]",
18
18
  };
19
19
  const __O = {
20
20
  hidden: "overflow-hidden",
21
21
  };
22
- const CLS_BADGE_NEW = "rounded-full bg-error-surface px-2 py-0.5 text-[10px] text-white shadow-sm";
23
- const CLS_BADGE_SALE = "rounded-full bg-success-surface px-2 py-0.5 text-[10px] font-bold text-white shadow-sm";
24
- const CLS_BADGE_TRENDING = "rounded-full bg-indigo-600 px-2 py-0.5 text-[10px] font-bold text-white shadow-sm";
25
- const CLS_BADGE_LIMITED = "rounded-full bg-info-surface px-2 py-0.5 text-[10px] font-bold text-white shadow-sm";
22
+ const CLS_BADGE_NEW = "rounded-full bg-error-surface px-[var(--appkit-space-2)] py-[var(--appkit-space-0-5)] text-[10px] text-white shadow-sm";
23
+ const CLS_BADGE_SALE = "rounded-full bg-success-surface px-[var(--appkit-space-2)] py-[var(--appkit-space-0-5)] text-[10px] font-bold text-white shadow-sm";
24
+ const CLS_BADGE_TRENDING = "rounded-full bg-indigo-600 px-[var(--appkit-space-2)] py-[var(--appkit-space-0-5)] text-[10px] font-bold text-white shadow-sm";
25
+ const CLS_BADGE_LIMITED = "rounded-full bg-info-surface px-[var(--appkit-space-2)] py-[var(--appkit-space-0-5)] text-[10px] font-bold text-white shadow-sm";
26
26
  const CLS_HEART_ACTIVE = "bg-error-surface text-white hover:bg-error-surface";
27
27
  const CLS_HEART_IDLE = "bg-white/90 bg-[var(--appkit-color-surface-elevated)]/90 text-[var(--appkit-color-text-muted)] hover:text-error hover:bg-[var(--appkit-color-surface)] hover:bg-[var(--appkit-color-surface-elevated)]";
28
28
  const CLS_STAR = "text-[11px] text-warning";
@@ -103,11 +103,11 @@ export function ProductCard({ product, href, onClick, onAddToWishlist, isWishlis
103
103
  e.stopPropagation();
104
104
  e.preventDefault();
105
105
  onBuyNow(product);
106
- }, className: "justify-center text-xs btn-glow", children: [_jsx("svg", { className: "h-3.5 w-3.5 flex-shrink-0", fill: "none", stroke: "currentColor", strokeWidth: 2.5, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M13 10V3L4 14h7v7l9-11h-7z" }) }), "Buy Now"] })), onAddToCart && (_jsxs(Button, { gap: "sm", type: "button", variant: "outline", size: "sm", onClick: (e) => {
106
+ }, className: "justify-center text-[length:var(--appkit-text-xs)] btn-glow", children: [_jsx("svg", { className: "h-3.5 w-3.5 flex-shrink-0", fill: "none", stroke: "currentColor", strokeWidth: 2.5, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M13 10V3L4 14h7v7l9-11h-7z" }) }), "Buy Now"] })), onAddToCart && (_jsxs(Button, { gap: "sm", type: "button", variant: "outline", size: "sm", onClick: (e) => {
107
107
  e.stopPropagation();
108
108
  e.preventDefault();
109
109
  onAddToCart(product);
110
- }, className: "justify-center text-xs", children: [_jsx("svg", { className: "h-3.5 w-3.5 flex-shrink-0", fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 3h2l.4 2M7 13h10l4-8H5.4m1.6 8L5 3H3m4 10v7a1 1 0 001 1h8a1 1 0 001-1v-7M9 21h6" }) }), "Cart"] }))] }))] })] })] }));
110
+ }, className: "justify-center text-[length:var(--appkit-text-xs)]", children: [_jsx("svg", { className: "h-3.5 w-3.5 flex-shrink-0", fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 3h2l.4 2M7 13h10l4-8H5.4m1.6 8L5 3H3m4 10v7a1 1 0 001 1h8a1 1 0 001-1v-7M9 21h6" }) }), "Cart"] }))] }))] })] })] }));
111
111
  if (href && !selectionMode) {
112
112
  return (_jsx(Link, { href: href, className: "block h-full", children: cardBody }));
113
113
  }
@@ -115,7 +115,7 @@ export function ProductCard({ product, href, onClick, onAddToWishlist, isWishlis
115
115
  }
116
116
  // --- Grid class maps ---------------------------------------------------------
117
117
  const GRID_CLASSES = {
118
- card: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-6",
118
+ card: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-[var(--appkit-space-6)]",
119
119
  };
120
120
  function ProductListRow({ product, onClick, onAddToWishlist, isWishlisted, }) {
121
121
  const discount = product.originalPrice && product.originalPrice > product.price
@@ -125,7 +125,7 @@ function ProductListRow({ product, onClick, onAddToWishlist, isWishlisted, }) {
125
125
  return (_jsxs(Div, { role: onClick ? "button" : undefined, tabIndex: onClick ? 0 : undefined, onKeyDown: onClick
126
126
  ? (e) => (e.key === "Enter" || e.key === " ") && onClick(product)
127
127
  : undefined, onClick: onClick ? () => onClick(product) : undefined, className: [
128
- "flex items-center gap-3 p-2 sm:p-3",
128
+ "flex items-center gap-[var(--appkit-space-3)] p-[var(--appkit-space-2)] sm:p-[var(--appkit-space-3)]",
129
129
  "hover:bg-[var(--appkit-color-surface)]/60 transition-colors",
130
130
  onClick ? "cursor-pointer" : "",
131
131
  ]
@@ -144,7 +144,7 @@ function ProductListRow({ product, onClick, onAddToWishlist, isWishlisted, }) {
144
144
  })()] })] }), onAddToWishlist && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: (e) => {
145
145
  e.stopPropagation();
146
146
  onAddToWishlist(product.id);
147
- }, "aria-label": isWishlisted ? "Remove from wishlist" : "Add to wishlist", className: `flex-shrink-0 h-8 w-8 flex items-center justify-center rounded-full text-base leading-none ${isWishlisted ? CLS_HEART_ROSE_ACTIVE : CLS_HEART_ROSE_IDLE}`, children: isWishlisted ? "♥" : "♡" }))] }));
147
+ }, "aria-label": isWishlisted ? "Remove from wishlist" : "Add to wishlist", className: `flex-shrink-0 h-8 w-8 flex items-center justify-center rounded-full text-[length:var(--appkit-text-base)] leading-none ${isWishlisted ? CLS_HEART_ROSE_ACTIVE : CLS_HEART_ROSE_IDLE}`, children: isWishlisted ? "♥" : "♡" }))] }));
148
148
  }
149
149
  function safeHref(href) {
150
150
  if (!href)
@@ -204,6 +204,6 @@ export function ProductGrid({ products, renderCard, onProductClick, getProductHr
204
204
  }) }));
205
205
  };
206
206
  return (_jsxs(Div, { children: [resolvedHeader, isEmpty
207
- ? (resolvedEmpty ?? (_jsx(Text, { paddingY: "3xl", color: "muted", size: "sm", align: "center", children: emptyLabel })))
207
+ ? (resolvedEmpty ?? (_jsx(Text, { paddingY: "3xl", color: "muted", size: "sm", align: "start", children: emptyLabel })))
208
208
  : renderItems(), resolvedFooter] }));
209
209
  }
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { Row } from "@mohasinac/appkit/ui";
3
+ import { Button, Row } from "@mohasinac/appkit/ui";
4
4
  import React from "react";
5
5
  import { Div } from "../../../ui/components/Div";
6
6
  const DEFAULT_TABS = [
@@ -19,7 +19,7 @@ export function ProductTabs({ renderDescription, renderSpecs, renderReviews, ext
19
19
  ...extraTabs,
20
20
  ];
21
21
  const tabs = allTabs.length > 0 ? allTabs : DEFAULT_TABS;
22
- return (_jsxs(Div, { className: className, children: [renderTabBar ? (renderTabBar(activeTab, setActiveTab, tabs)) : (_jsx(Row, { gap: "md", className: "border-b mb-4", children: tabs.map((t) => (_jsx("button", { onClick: () => setActiveTab(t.value), className: `pb-2 text-sm font-medium border-b-2 transition-colors ${activeTab === t.value
22
+ return (_jsxs(Div, { className: className, children: [renderTabBar ? (renderTabBar(activeTab, setActiveTab, tabs)) : (_jsx(Row, { gap: "md", className: "border-b mb-4", children: tabs.map((t) => (_jsx(Button, { variant: "ghost", type: "button", onClick: () => setActiveTab(t.value), paddingX: "none", paddingY: "xs", textSize: "sm", weight: "medium", rounded: "none", className: `border-b-2 transition-colors ${activeTab === t.value
23
23
  ? "border-current text-current"
24
24
  : "border-transparent text-[var(--appkit-color-text-muted)]"}`, children: t.label }, t.value))) })), activeTab === "description" && renderDescription?.(), activeTab === "specs" && renderSpecs?.(), activeTab === "reviews" && renderReviews?.(), renderExtraTab?.(activeTab)] }));
25
25
  }
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState } from "react";
4
+ import { Button } from "../../../ui/components/Button";
4
5
  import { Div } from "../../../ui/components/Div";
5
6
  const __O = {
6
7
  xAuto: "overflow-x-auto",
@@ -39,7 +40,7 @@ export function ProductTabsShell({ descriptionContent, specsContent, gradingCont
39
40
  if (allTabs.length === 0)
40
41
  return null;
41
42
  const activeContent = allTabs.find((t) => t.id === activeId)?.content;
42
- return (_jsxs(Div, { className: `mt-8 ${className}`, children: [_jsx(Div, { layout: "flex", gap: "1", border: "default", className: `mb-6 ${__O.xAuto} border-b pb-px`, children: allTabs.map((t) => (_jsx("button", { type: "button", onClick: () => setActiveId(t.id), className: `flex-shrink-0 -mb-px pb-3 px-4 text-sm font-medium border-b-2 transition-colors ${activeId === t.id
43
+ return (_jsxs(Div, { className: `mt-8 ${className}`, children: [_jsx(Div, { layout: "flex", gap: "1", border: "default", className: `mb-6 ${__O.xAuto} border-b pb-px`, children: allTabs.map((t) => (_jsx(Button, { variant: "ghost", type: "button", onClick: () => setActiveId(t.id), paddingX: "md", paddingY: "none", textSize: "sm", weight: "medium", rounded: "none", className: `flex-shrink-0 -mb-px pb-[var(--appkit-space-3)] border-b-2 transition-colors ${activeId === t.id
43
44
  ? "border-[var(--appkit-color-primary)] text-[var(--appkit-color-primary)]"
44
45
  : "border-transparent text-[var(--appkit-color-text-muted)] hover:text-[var(--appkit-color-text-muted)]"}`, children: t.label }, t.id))) }), _jsx("div", { children: activeContent })] }));
45
46
  }
@@ -24,7 +24,7 @@ import { sortBy } from "../../../constants/sort";
24
24
  import { PRODUCT_FIELDS } from "../../../constants/field-names";
25
25
  import { useBottomActions } from "../../layout";
26
26
  const __P = {
27
- p3: "p-3",
27
+ p3: "p-[var(--appkit-space-3)]",
28
28
  };
29
29
  const __O = {
30
30
  hidden: "overflow-hidden",
@@ -189,6 +189,11 @@ export function ProductsIndexListing({ initialData }) {
189
189
  ] } } : {});
190
190
  return (_jsxs(Div, { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: filterActiveCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search products...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, onSearchKeyDown: handleSearchKeyDown, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: PRODUCT_PUBLIC_SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, view: view, onViewChange: handleViewToggle, onResetAll: resetAll, hasActiveState: hasActiveState, bulkMode: selection.isSelecting, bulkSelectedCount: selection.selectedCount, bulkTotalCount: products.length, onBulkSelectAll: selection.toggleAll, onBulkClear: selection.clearSelection, toggles: [
191
191
  { label: "Show sold", active: showSold, onChange: (next) => table.set(TABLE_KEYS.SHOW_SOLD, next ? "true" : "") },
192
+ // Inline quick-filter: the highest-frequency drawer-only facet promoted
193
+ // to the sticky toolbar so it doesn't require open-drawer → check → Apply
194
+ // → close for every toggle. The full facet set (category/price/brand/…)
195
+ // remains in <FilterDrawer> below.
196
+ { label: "Free shipping", active: table.get(TABLE_KEYS.FREE_SHIPPING) === "true", onChange: (next) => table.set(TABLE_KEYS.FREE_SHIPPING, next ? "true" : "") },
192
197
  ] }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
193
198
  {
194
199
  id: ACTION_ID.ADD_TO_CART,
@@ -2,6 +2,7 @@
2
2
  import { jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { normalizeError } from "../../../errors/normalize";
4
4
  import { useState } from "react";
5
+ import { Button } from "../../../ui/components/Button";
5
6
  export function ShareButton({ title, text, className = "" }) {
6
7
  const [copied, setCopied] = useState(false);
7
8
  const handleShare = async () => {
@@ -20,5 +21,5 @@ export function ShareButton({ title, text, className = "" }) {
20
21
  setCopied(true);
21
22
  setTimeout(() => setCopied(false), 2000);
22
23
  };
23
- return (_jsxs("button", { type: "button", onClick: handleShare, className: `inline-flex items-center gap-1.5 rounded-lg border border-[var(--appkit-color-border)] px-3 py-1.5 text-sm font-medium text-[var(--appkit-color-text-muted)] hover:bg-[var(--appkit-color-surface)] transition-colors ${className}`, "aria-label": "Share this page", children: ["\uD83D\uDD17 ", copied ? "Link Copied!" : "Share"] }));
24
+ return (_jsxs(Button, { variant: "outline", type: "button", onClick: handleShare, gap: "sm", rounded: "lg", paddingX: "sm", paddingY: "xs", textSize: "sm", weight: "medium", textColor: "muted", className: `hover:bg-[var(--appkit-color-surface)] ${className}`, "aria-label": "Share this page", children: ["\uD83D\uDD17 ", copied ? "Link Copied!" : "Share"] }));
24
25
  }