@mohasinac/appkit 2.8.2 → 2.8.4

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 (451) hide show
  1. package/dist/_internal/client/features/classified/ClassifiedDetailView.js +7 -1
  2. package/dist/_internal/client/features/digital-code/CodeRevealPanel.js +4 -1
  3. package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.js +7 -1
  4. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +3 -2
  5. package/dist/_internal/client/features/live/LiveItemDetailView.js +11 -2
  6. package/dist/_internal/client/scaffolds/AppShell.js +2 -1
  7. package/dist/_internal/client/scaffolds/DashboardScaffold.js +2 -1
  8. package/dist/_internal/server/features/checkout/actions.js +40 -39
  9. package/dist/_internal/shared/actions/action-registry.js +6 -0
  10. package/dist/_internal/shared/config/index.d.ts +1 -1
  11. package/dist/_internal/shared/config/schema.d.ts +0 -8
  12. package/dist/client-entry.d.ts +1 -1
  13. package/dist/client.d.ts +3 -1
  14. package/dist/client.js +3 -1
  15. package/dist/configs/next.js +12 -22
  16. package/dist/constants/api-endpoints.d.ts +6 -0
  17. package/dist/constants/api-endpoints.js +2 -0
  18. package/dist/features/about/components/AboutView.js +5 -2
  19. package/dist/features/about/components/FAQPageView.js +3 -3
  20. package/dist/features/about/components/FeesView.js +13 -5
  21. package/dist/features/about/components/HelpPageView.js +9 -5
  22. package/dist/features/about/components/HowAuctionsWorkView.js +9 -5
  23. package/dist/features/about/components/HowCheckoutWorksView.js +9 -5
  24. package/dist/features/about/components/HowOffersWorkView.js +10 -5
  25. package/dist/features/about/components/HowOrdersWorkView.js +10 -5
  26. package/dist/features/about/components/HowPayoutsWorkView.js +9 -5
  27. package/dist/features/about/components/HowPreOrdersWorkView.js +9 -5
  28. package/dist/features/about/components/HowReviewsWorkView.js +9 -5
  29. package/dist/features/about/components/PolicyPageView.js +3 -3
  30. package/dist/features/about/components/PublicProfileView.js +11 -4
  31. package/dist/features/about/components/SecurityPrivacyView.js +8 -4
  32. package/dist/features/about/components/ShippingPolicyView.js +3 -2
  33. package/dist/features/about/components/TrackOrderView.js +2 -2
  34. package/dist/features/about/components/UnauthorizedView.js +3 -3
  35. package/dist/features/account/components/AddressBook.js +1 -1
  36. package/dist/features/account/components/AddressForm.js +2 -2
  37. package/dist/features/account/components/AddressInlineSelect.d.ts +24 -0
  38. package/dist/features/account/components/AddressInlineSelect.js +78 -0
  39. package/dist/features/account/components/AddressSelectorCreate.d.ts +2 -1
  40. package/dist/features/account/components/AddressSelectorCreate.js +5 -32
  41. package/dist/features/account/components/AddressesIndexListing.js +3 -3
  42. package/dist/features/account/components/ChatWindow.js +2 -1
  43. package/dist/features/account/components/NotificationBell.js +13 -7
  44. package/dist/features/account/components/NotificationPreferencesPanel.js +4 -1
  45. package/dist/features/account/components/UserOffersPanel.js +2 -1
  46. package/dist/features/account/components/UserSidebar.js +11 -7
  47. package/dist/features/account/components/UserSupportView.js +13 -4
  48. package/dist/features/account/components/index.d.ts +2 -0
  49. package/dist/features/account/components/index.js +1 -0
  50. package/dist/features/addresses/repository/addresses.repository.d.ts +1 -0
  51. package/dist/features/addresses/repository/addresses.repository.js +13 -0
  52. package/dist/features/admin/components/AdminAdEditorView.js +8 -5
  53. package/dist/features/admin/components/AdminAddressEditorView.js +5 -5
  54. package/dist/features/admin/components/AdminAdsView.js +10 -7
  55. package/dist/features/admin/components/AdminAllEventEntriesView.js +5 -3
  56. package/dist/features/admin/components/AdminBidsView.js +6 -4
  57. package/dist/features/admin/components/AdminBlogEditorView.js +15 -9
  58. package/dist/features/admin/components/AdminBlogView.js +6 -4
  59. package/dist/features/admin/components/AdminBrandEditorView.js +10 -4
  60. package/dist/features/admin/components/AdminBrandsView.js +12 -10
  61. package/dist/features/admin/components/AdminBundleEditorView.js +4 -5
  62. package/dist/features/admin/components/AdminBundlesView.js +13 -11
  63. package/dist/features/admin/components/AdminCarouselEditorView.js +6 -3
  64. package/dist/features/admin/components/AdminCarouselView.js +6 -6
  65. package/dist/features/admin/components/AdminCartsView.js +6 -4
  66. package/dist/features/admin/components/AdminCatalogGuideView.js +2 -1
  67. package/dist/features/admin/components/AdminCategoriesView.js +12 -10
  68. package/dist/features/admin/components/AdminCategoryEditorView.js +11 -5
  69. package/dist/features/admin/components/AdminClassifiedView.js +4 -3
  70. package/dist/features/admin/components/AdminContactEditorView.js +8 -1
  71. package/dist/features/admin/components/AdminContactView.js +6 -4
  72. package/dist/features/admin/components/AdminCouponEditorView.js +23 -5
  73. package/dist/features/admin/components/AdminCouponsView.js +6 -4
  74. package/dist/features/admin/components/AdminDigitalCodesView.js +4 -3
  75. package/dist/features/admin/components/AdminEmployeeEditorView.js +7 -4
  76. package/dist/features/admin/components/AdminFaqEditorView.js +9 -3
  77. package/dist/features/admin/components/AdminFaqsView.js +9 -7
  78. package/dist/features/admin/components/AdminFeatureEditorView.js +7 -1
  79. package/dist/features/admin/components/AdminFeatureFlagsView.js +4 -1
  80. package/dist/features/admin/components/AdminFeaturesView.js +5 -4
  81. package/dist/features/admin/components/AdminFilterBar.js +4 -4
  82. package/dist/features/admin/components/AdminGroupedListingsView.js +66 -30
  83. package/dist/features/admin/components/AdminGuideHubView.js +4 -1
  84. package/dist/features/admin/components/AdminHistoryView.js +4 -3
  85. package/dist/features/admin/components/AdminLiveView.js +4 -3
  86. package/dist/features/admin/components/AdminMediaView.js +4 -1
  87. package/dist/features/admin/components/AdminNavigationView.js +7 -4
  88. package/dist/features/admin/components/AdminNewsletterView.js +5 -3
  89. package/dist/features/admin/components/AdminNotificationsView.js +8 -6
  90. package/dist/features/admin/components/AdminOrderEditorView.js +2 -2
  91. package/dist/features/admin/components/AdminOrdersView.js +6 -4
  92. package/dist/features/admin/components/AdminPageHeader.js +5 -2
  93. package/dist/features/admin/components/AdminPayoutsView.js +7 -5
  94. package/dist/features/admin/components/AdminPrizeDrawsView.js +11 -9
  95. package/dist/features/admin/components/AdminProductEditorView.js +12 -5
  96. package/dist/features/admin/components/AdminProductsView.js +11 -9
  97. package/dist/features/admin/components/AdminReturnRequestsView.js +4 -3
  98. package/dist/features/admin/components/AdminReviewsView.js +10 -8
  99. package/dist/features/admin/components/AdminScammerEditorView.js +6 -2
  100. package/dist/features/admin/components/AdminScammersView.js +11 -9
  101. package/dist/features/admin/components/AdminSectionsView.js +20 -22
  102. package/dist/features/admin/components/AdminSessionsManager.js +2 -1
  103. package/dist/features/admin/components/AdminSessionsView.js +8 -6
  104. package/dist/features/admin/components/AdminSidebar.js +11 -7
  105. package/dist/features/admin/components/AdminSiteConfigGuideView.js +2 -1
  106. package/dist/features/admin/components/AdminSiteSettingsView.js +5 -1
  107. package/dist/features/admin/components/AdminStoreAddressesView.js +4 -3
  108. package/dist/features/admin/components/AdminStoreEditorView.js +5 -5
  109. package/dist/features/admin/components/AdminStoresView.js +6 -4
  110. package/dist/features/admin/components/AdminSublistingCategoriesView.js +6 -5
  111. package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +3 -3
  112. package/dist/features/admin/components/AdminSupportTicketDetailView.js +10 -3
  113. package/dist/features/admin/components/AdminSupportTicketsView.js +11 -9
  114. package/dist/features/admin/components/AdminTeamView.js +6 -4
  115. package/dist/features/admin/components/AdminTrustGuideView.js +3 -3
  116. package/dist/features/admin/components/AdminUsersGuideView.js +3 -3
  117. package/dist/features/admin/components/AdminUsersView.js +6 -4
  118. package/dist/features/admin/components/AdminViewCards.js +12 -6
  119. package/dist/features/admin/components/AdminWishlistsView.js +4 -3
  120. package/dist/features/admin/components/BrandQuickCreateForm.js +2 -2
  121. package/dist/features/admin/components/CategoryQuickCreateForm.js +2 -2
  122. package/dist/features/admin/components/DashboardStats.js +9 -3
  123. package/dist/features/admin/components/DataListingView.js +3 -3
  124. package/dist/features/admin/components/DataTable.js +11 -7
  125. package/dist/features/admin/components/DrawerFormFooter.js +2 -2
  126. package/dist/features/admin/components/QuickEditMenu.js +2 -1
  127. package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +5 -1
  128. package/dist/features/admin/constants/filter-tabs.d.ts +1 -1
  129. package/dist/features/admin/constants/filter-tabs.js +0 -11
  130. package/dist/features/admin/types/index.d.ts +1 -1
  131. package/dist/features/auctions/actions/bid-actions.js +4 -2
  132. package/dist/features/auctions/components/AuctionBidsTable.js +4 -1
  133. package/dist/features/auctions/components/AuctionDetailPageView.js +14 -6
  134. package/dist/features/auctions/components/AuctionsListView.js +7 -6
  135. package/dist/features/auctions/components/CollapsibleBidHistory.js +5 -1
  136. package/dist/features/auctions/components/MarketplaceAuctionCard.js +9 -3
  137. package/dist/features/auctions/components/MarketplaceAuctionGrid.js +8 -2
  138. package/dist/features/auctions/components/PlaceBidFormClient.js +4 -1
  139. package/dist/features/auth/components/RegisterForm.js +2 -2
  140. package/dist/features/auth/components/VerifyEmailView.js +5 -2
  141. package/dist/features/before-after/components/BeforeAfterSlider.js +1 -1
  142. package/dist/features/blog/actions/blog-actions.js +3 -2
  143. package/dist/features/blog/components/BlogFeaturedCard.js +8 -1
  144. package/dist/features/blog/components/BlogIndexListing.js +11 -5
  145. package/dist/features/blog/components/BlogListView.js +11 -3
  146. package/dist/features/blog/components/BlogPostView.js +10 -3
  147. package/dist/features/cart/components/CartDrawer.js +11 -3
  148. package/dist/features/cart/components/CartSummary.js +2 -2
  149. package/dist/features/cart/components/CheckoutOtpModal.js +2 -1
  150. package/dist/features/categories/components/BrandDetailPageView.js +15 -10
  151. package/dist/features/categories/components/BrandDetailTabs.js +5 -1
  152. package/dist/features/categories/components/BundleDetailView.js +6 -3
  153. package/dist/features/categories/components/BundleDynamicRuleEditor.js +3 -1
  154. package/dist/features/categories/components/BundleItemsPicker.js +10 -3
  155. package/dist/features/categories/components/CategoriesIndexListing.js +13 -7
  156. package/dist/features/categories/components/CategoriesIndexPageView.js +5 -4
  157. package/dist/features/categories/components/CategoryBundlesListing.js +10 -6
  158. package/dist/features/categories/components/CategoryDetailPageView.js +18 -12
  159. package/dist/features/categories/components/CategoryDetailTabs.js +5 -1
  160. package/dist/features/categories/components/CategoryFilters.d.ts +12 -12
  161. package/dist/features/categories/components/CategoryFilters.js +13 -12
  162. package/dist/features/categories/components/CategoryForm.js +6 -3
  163. package/dist/features/categories/components/CategoryGrid.js +9 -2
  164. package/dist/features/categories/components/CategoryProductsListing.js +10 -4
  165. package/dist/features/categories/components/CategorySelectorCreate.js +3 -3
  166. package/dist/features/categories/components/CategorySortSelect.js +1 -1
  167. package/dist/features/categories/components/CategoryStoresListing.js +3 -3
  168. package/dist/features/categories/components/CategoryTableColumns.js +10 -6
  169. package/dist/features/categories/components/CategoryTree.d.ts +1 -1
  170. package/dist/features/categories/components/CategoryTree.js +2 -2
  171. package/dist/features/categories/schemas/firestore.d.ts +2 -2
  172. package/dist/features/checkout/actions/checkout-actions.d.ts +1 -1
  173. package/dist/features/checkout/actions/checkout-actions.js +1 -1
  174. package/dist/features/classified/components/ClassifiedFilters.js +2 -2
  175. package/dist/features/classified/components/ClassifiedIndexListing.js +9 -3
  176. package/dist/features/classified/components/ClassifiedListView.js +6 -5
  177. package/dist/features/collections/components/CollectionCard.js +2 -1
  178. package/dist/features/contact/components/ContactForm.js +4 -2
  179. package/dist/features/contact/components/ContactInfoSidebar.js +4 -1
  180. package/dist/features/copilot/components/AdminCopilotView.js +13 -5
  181. package/dist/features/cron/jobs/auction-expiry.job.d.ts +2 -2
  182. package/dist/features/cron/jobs/auction-expiry.job.js +2 -1
  183. package/dist/features/cron/jobs/preorder-reminder.job.d.ts +1 -1
  184. package/dist/features/cron/jobs/preorder-reminder.job.js +2 -1
  185. package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +9 -3
  186. package/dist/features/digital-codes/components/DigitalCodesListView.js +4 -3
  187. package/dist/features/events/actions/event-actions.js +6 -4
  188. package/dist/features/events/components/AdminEventEditorView.js +63 -41
  189. package/dist/features/events/components/AdminEventEntriesView.js +9 -6
  190. package/dist/features/events/components/AdminEventsView.js +7 -5
  191. package/dist/features/events/components/EventCard.js +7 -1
  192. package/dist/features/events/components/EventFilters.d.ts +4 -4
  193. package/dist/features/events/components/EventFilters.js +2 -2
  194. package/dist/features/events/components/EventFormDrawer.js +2 -1
  195. package/dist/features/events/components/EventLeaderboard.js +4 -4
  196. package/dist/features/events/components/EventOfferCard.js +4 -1
  197. package/dist/features/events/components/EventParticipateView.js +3 -2
  198. package/dist/features/events/components/EventPollWidget.js +6 -5
  199. package/dist/features/events/components/EventRaffleEntryForm.js +5 -2
  200. package/dist/features/events/components/EventRaffleWinnerView.js +7 -1
  201. package/dist/features/events/components/EventRafflesSection.js +6 -4
  202. package/dist/features/events/components/EventSaleBanner.js +5 -2
  203. package/dist/features/events/components/EventsIndexListing.js +8 -2
  204. package/dist/features/events/components/EventsListView.js +4 -1
  205. package/dist/features/events/components/SpinWheelView.js +7 -2
  206. package/dist/features/events/schemas/firestore.d.ts +1 -0
  207. package/dist/features/events/types/index.d.ts +1 -0
  208. package/dist/features/faq/actions/faq-actions.js +4 -2
  209. package/dist/features/faq/components/ContactCTA.js +4 -1
  210. package/dist/features/faq/components/FAQCategorySidebar.js +2 -2
  211. package/dist/features/faq/components/FAQHelpfulButtons.js +8 -5
  212. package/dist/features/faq/components/FAQPageContent.js +7 -6
  213. package/dist/features/faq/components/FAQSortDropdown.js +2 -2
  214. package/dist/features/filters/AsyncFacetSection.js +4 -2
  215. package/dist/features/filters/FilterFacetSection.js +14 -6
  216. package/dist/features/filters/RangeFilter.js +4 -2
  217. package/dist/features/filters/SwitchFilter.js +2 -1
  218. package/dist/features/forms/Checkbox.js +1 -1
  219. package/dist/features/forms/Radio.js +1 -1
  220. package/dist/features/forms/Slider.js +1 -1
  221. package/dist/features/homepage/components/AdSlot.js +4 -4
  222. package/dist/features/homepage/components/AdvertisementBanner.js +13 -4
  223. package/dist/features/homepage/components/AnnouncementBar.js +2 -1
  224. package/dist/features/homepage/components/BeforeAfterCard.js +8 -2
  225. package/dist/features/homepage/components/BrandsSection.js +6 -3
  226. package/dist/features/homepage/components/CTABannerSection.js +2 -2
  227. package/dist/features/homepage/components/CharacterHotspot.js +5 -2
  228. package/dist/features/homepage/components/CharacterHotspotForm.js +8 -4
  229. package/dist/features/homepage/components/CustomCardsSection.js +13 -7
  230. package/dist/features/homepage/components/CustomerReviewsSection.js +9 -3
  231. package/dist/features/homepage/components/FAQSection.js +7 -4
  232. package/dist/features/homepage/components/FeaturedBundlesSection.js +8 -2
  233. package/dist/features/homepage/components/FeaturedResultsSection.js +1 -1
  234. package/dist/features/homepage/components/GoogleReviewsSection.js +14 -8
  235. package/dist/features/homepage/components/HeroCarousel.js +1 -1
  236. package/dist/features/homepage/components/HomepageSkeleton.js +7 -1
  237. package/dist/features/homepage/components/HowItWorksInfoView.js +2 -2
  238. package/dist/features/homepage/components/HowItWorksSection.js +2 -2
  239. package/dist/features/homepage/components/MarketplaceHomepageView.js +4 -2
  240. package/dist/features/homepage/components/NewsletterBanner.js +3 -2
  241. package/dist/features/homepage/components/NewsletterSection.js +5 -2
  242. package/dist/features/homepage/components/PromoGrid.js +4 -1
  243. package/dist/features/homepage/components/SectionCarousel.js +7 -4
  244. package/dist/features/homepage/components/SecurityHighlightsSection.js +3 -3
  245. package/dist/features/homepage/components/ShopByCategorySection.js +10 -4
  246. package/dist/features/homepage/components/SiteFeaturesSection.js +5 -2
  247. package/dist/features/homepage/components/SocialFeedSection.js +4 -4
  248. package/dist/features/homepage/components/SocialPostCard.js +6 -3
  249. package/dist/features/homepage/components/TrustFeaturesSection.js +5 -5
  250. package/dist/features/homepage/components/TrustIndicatorsSection.js +5 -2
  251. package/dist/features/homepage/components/WelcomeSection.js +1 -1
  252. package/dist/features/homepage/components/WhatsAppCommunitySection.js +3 -3
  253. package/dist/features/layout/AppLayoutShell.js +2 -1
  254. package/dist/features/layout/BackToTop.js +1 -1
  255. package/dist/features/layout/BottomActions.js +4 -30
  256. package/dist/features/layout/BottomActionsContext.d.ts +0 -36
  257. package/dist/features/layout/BottomActionsContext.js +0 -36
  258. package/dist/features/layout/BottomNavItem.js +1 -1
  259. package/dist/features/layout/BottomSheet.js +4 -1
  260. package/dist/features/layout/FooterLayout.js +1 -1
  261. package/dist/features/layout/NavbarLayout.js +4 -1
  262. package/dist/features/layout/SidebarLayout.js +5 -2
  263. package/dist/features/live/components/LiveItemFilters.js +2 -2
  264. package/dist/features/live/components/LiveItemsIndexListing.js +9 -3
  265. package/dist/features/live/components/LiveItemsListView.js +6 -5
  266. package/dist/features/loyalty/components/CoinsDisplay.js +4 -2
  267. package/dist/features/media/AvatarUpload.js +2 -2
  268. package/dist/features/media/MediaLightbox.js +3 -2
  269. package/dist/features/media/modals/VideoThumbnailSelector.js +4 -1
  270. package/dist/features/media/modals/VideoTrimModal.js +1 -1
  271. package/dist/features/media/upload/CameraCapture.js +1 -1
  272. package/dist/features/media/upload/ImageUpload.js +4 -1
  273. package/dist/features/media/upload/MediaUploadField.js +11 -2
  274. package/dist/features/media/upload/MediaUploadList.js +5 -1
  275. package/dist/features/orders/components/MarketplaceOrderCard.js +2 -2
  276. package/dist/features/orders/components/OrdersList.js +2 -1
  277. package/dist/features/orders/components/RefundHistoryTable.js +4 -1
  278. package/dist/features/orders/components/RefundRequestView.js +2 -1
  279. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +5 -1
  280. package/dist/features/pre-orders/components/PreOrderActionsClient.js +3 -3
  281. package/dist/features/pre-orders/components/PreOrderBadge.js +2 -1
  282. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +16 -7
  283. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +32 -24
  284. package/dist/features/pre-orders/components/PreOrdersListView.js +5 -4
  285. package/dist/features/products/actions/product-actions.js +17 -15
  286. package/dist/features/products/columns/index.d.ts +1 -1
  287. package/dist/features/products/columns/index.js +1 -1
  288. package/dist/features/products/columns/productTableColumns.js +9 -4
  289. package/dist/features/products/components/AuctionsIndexListing.js +9 -3
  290. package/dist/features/products/components/BidHistory.js +4 -4
  291. package/dist/features/products/components/CompareOverlay.js +10 -2
  292. package/dist/features/products/components/CustomFieldsEditor.js +2 -1
  293. package/dist/features/products/components/CustomSectionTabContent.js +2 -2
  294. package/dist/features/products/components/CustomSectionsEditor.js +3 -2
  295. package/dist/features/products/components/GroupSettingsPanel.js +34 -26
  296. package/dist/features/products/components/MakeOfferButton.js +6 -2
  297. package/dist/features/products/components/MakeOfferForm.js +2 -1
  298. package/dist/features/products/components/MarketplaceBundleCard.js +6 -3
  299. package/dist/features/products/components/MarketplacePrizeDrawCard.js +3 -2
  300. package/dist/features/products/components/PlaceBidForm.js +2 -1
  301. package/dist/features/products/components/PrizeDrawCollage.js +6 -16
  302. package/dist/features/products/components/PrizeDrawDetailPageView.js +6 -1
  303. package/dist/features/products/components/PrizeDrawItemsEditor.js +4 -2
  304. package/dist/features/products/components/PrizeDrawsIndexListing.js +6 -3
  305. package/dist/features/products/components/PrizeDrawsListingView.js +5 -4
  306. package/dist/features/products/components/PrizeDrawsSection.js +6 -4
  307. package/dist/features/products/components/PrizeRevealModal.js +5 -1
  308. package/dist/features/products/components/ProductDetailPageView.js +32 -16
  309. package/dist/features/products/components/ProductFeatureBadges.js +9 -9
  310. package/dist/features/products/components/ProductForm.d.ts +11 -1
  311. package/dist/features/products/components/ProductForm.js +10 -5
  312. package/dist/features/products/components/ProductGalleryClient.js +8 -4
  313. package/dist/features/products/components/ProductGradingTab.js +4 -1
  314. package/dist/features/products/components/ProductGrid.js +35 -14
  315. package/dist/features/products/components/ProductInfo.js +2 -1
  316. package/dist/features/products/components/ProductTabs.js +2 -1
  317. package/dist/features/products/components/ProductTabsShell.js +5 -1
  318. package/dist/features/products/components/ProductsIndexListing.js +32 -24
  319. package/dist/features/products/components/ProductsIndexPageView.js +2 -2
  320. package/dist/features/products/components/RelatedProducts.js +3 -3
  321. package/dist/features/products/components/ShowGroupSection.js +10 -6
  322. package/dist/features/products/components/SublistingCarouselSection.js +7 -3
  323. package/dist/features/products/components/SublistingCategorySelect.d.ts +3 -1
  324. package/dist/features/products/components/SublistingCategorySelect.js +4 -37
  325. package/dist/features/products/constants/action-defs.js +3 -3
  326. package/dist/features/products/constants/sieve.d.ts +2 -2
  327. package/dist/features/products/constants/sieve.js +2 -2
  328. package/dist/features/products/hooks/useRelatedProducts.js +5 -4
  329. package/dist/features/promotions/components/CouponCard.js +5 -3
  330. package/dist/features/promotions/components/CouponsIndexListing.js +7 -3
  331. package/dist/features/promotions/repository/coupons.repository.d.ts +8 -0
  332. package/dist/features/promotions/repository/coupons.repository.js +2 -0
  333. package/dist/features/reviews/actions/review-actions.js +2 -1
  334. package/dist/features/reviews/components/ReviewDetailPageView.js +3 -3
  335. package/dist/features/reviews/components/ReviewDetailShell.js +15 -3
  336. package/dist/features/reviews/components/ReviewSummary.js +4 -2
  337. package/dist/features/reviews/components/ReviewsIndexListing.js +8 -2
  338. package/dist/features/reviews/components/ReviewsIndexPageView.js +7 -6
  339. package/dist/features/reviews/components/ReviewsList.js +1 -1
  340. package/dist/features/scams/actions/scam-actions.js +3 -2
  341. package/dist/features/scams/components/ScamAwarenessModal.js +2 -2
  342. package/dist/features/scams/components/ScamProfileView.js +3 -3
  343. package/dist/features/scams/components/ScamRegistryView.js +11 -8
  344. package/dist/features/search/actions/search-actions.js +7 -6
  345. package/dist/features/search/components/Search.js +9 -6
  346. package/dist/features/search/components/SearchFiltersRow.js +1 -1
  347. package/dist/features/search/components/SearchResultsSection.js +1 -1
  348. package/dist/features/seller/components/CouponInlineSelect.d.ts +22 -0
  349. package/dist/features/seller/components/CouponInlineSelect.js +104 -0
  350. package/dist/features/seller/components/GroupInlineSelect.d.ts +23 -0
  351. package/dist/features/seller/components/GroupInlineSelect.js +80 -0
  352. package/dist/features/seller/components/PhysicalLocationModal.js +2 -1
  353. package/dist/features/seller/components/PrintCenterView.js +2 -1
  354. package/dist/features/seller/components/ProductInlineSelect.d.ts +24 -0
  355. package/dist/features/seller/components/ProductInlineSelect.js +42 -0
  356. package/dist/features/seller/components/QuickProductForm.js +4 -1
  357. package/dist/features/seller/components/SellerAddressesView.js +8 -3
  358. package/dist/features/seller/components/SellerAnalyticsAlertsView.js +6 -3
  359. package/dist/features/seller/components/SellerAnalyticsView.js +2 -2
  360. package/dist/features/seller/components/SellerAuctionsView.js +7 -5
  361. package/dist/features/seller/components/SellerBidsView.js +12 -10
  362. package/dist/features/seller/components/SellerBundlesView.js +9 -7
  363. package/dist/features/seller/components/SellerClassifiedView.js +6 -5
  364. package/dist/features/seller/components/SellerCouponEditorView.d.ts +2 -0
  365. package/dist/features/seller/components/SellerCouponEditorView.js +15 -3
  366. package/dist/features/seller/components/SellerCouponsView.js +7 -5
  367. package/dist/features/seller/components/SellerDashboardView.js +2 -2
  368. package/dist/features/seller/components/SellerDigitalCodesView.js +7 -6
  369. package/dist/features/seller/components/SellerGoogleReviewsView.js +2 -2
  370. package/dist/features/seller/components/SellerGroupedListingsView.js +10 -9
  371. package/dist/features/seller/components/SellerLiveView.js +6 -5
  372. package/dist/features/seller/components/SellerOffersView.js +6 -4
  373. package/dist/features/seller/components/SellerOrdersView.js +18 -13
  374. package/dist/features/seller/components/SellerPayoutMethodsView.js +8 -6
  375. package/dist/features/seller/components/SellerPayoutRequestView.js +5 -1
  376. package/dist/features/seller/components/SellerPayoutSettingsView.js +5 -2
  377. package/dist/features/seller/components/SellerPayoutsView.js +6 -4
  378. package/dist/features/seller/components/SellerPreOrdersView.js +12 -10
  379. package/dist/features/seller/components/SellerPrizeDrawsView.js +12 -10
  380. package/dist/features/seller/components/SellerProductShell.js +1 -1
  381. package/dist/features/seller/components/SellerProductsCards.js +4 -1
  382. package/dist/features/seller/components/SellerProductsView.js +14 -12
  383. package/dist/features/seller/components/SellerReviewsView.js +7 -3
  384. package/dist/features/seller/components/SellerShippingConfigsView.js +7 -6
  385. package/dist/features/seller/components/SellerShippingView.js +1 -1
  386. package/dist/features/seller/components/SellerSidebar.js +15 -8
  387. package/dist/features/seller/components/SellerStoreCategoriesView.js +5 -4
  388. package/dist/features/seller/components/SellerStorefrontView.js +2 -2
  389. package/dist/features/seller/components/SellerTemplatesView.js +11 -7
  390. package/dist/features/seller/components/SublistingInlineSelect.d.ts +19 -0
  391. package/dist/features/seller/components/SublistingInlineSelect.js +84 -0
  392. package/dist/features/seller/components/analytics/SellerTopProducts.js +1 -1
  393. package/dist/features/seller/components/index.d.ts +8 -0
  394. package/dist/features/seller/components/index.js +4 -0
  395. package/dist/features/shell/FormShell.js +10 -2
  396. package/dist/features/shell/QuickFormDrawer.js +5 -5
  397. package/dist/features/shell/StepForm.js +6 -6
  398. package/dist/features/site-settings/components/ActionPermissionsManager.js +8 -4
  399. package/dist/features/site-settings/components/NavPermissionsManager.js +7 -4
  400. package/dist/features/stores/actions/store-query-actions.js +3 -2
  401. package/dist/features/stores/components/InteractiveStoreCard.js +5 -1
  402. package/dist/features/stores/components/StoreAboutView.js +4 -1
  403. package/dist/features/stores/components/StoreAddressSelectorCreate.d.ts +2 -1
  404. package/dist/features/stores/components/StoreAddressSelectorCreate.js +5 -31
  405. package/dist/features/stores/components/StoreAuctionsListing.js +6 -3
  406. package/dist/features/stores/components/StoreAuctionsPageView.js +4 -2
  407. package/dist/features/stores/components/StoreDetailLayoutView.d.ts +1 -1
  408. package/dist/features/stores/components/StoreDetailLayoutView.js +7 -6
  409. package/dist/features/stores/components/StoreGuideHubView.js +5 -2
  410. package/dist/features/stores/components/StoreHeader.js +8 -1
  411. package/dist/features/stores/components/StorePreOrdersListing.js +6 -3
  412. package/dist/features/stores/components/StorePreOrdersPageView.js +4 -2
  413. package/dist/features/stores/components/StorePrizeDrawsPageView.js +4 -2
  414. package/dist/features/stores/components/StoreProductsListing.js +6 -3
  415. package/dist/features/stores/components/StoreProductsPageView.js +2 -1
  416. package/dist/features/stores/components/StoreProductsView.js +5 -4
  417. package/dist/features/stores/components/StoreReviewsListing.js +8 -2
  418. package/dist/features/stores/components/StoresIndexListing.js +16 -9
  419. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +7 -1
  420. package/dist/features/whatsapp-bot/components/WhatsAppChatButton.js +2 -1
  421. package/dist/features/wishlist/components/WishlistPage.js +2 -1
  422. package/dist/features/wishlist/components/WishlistView.js +4 -3
  423. package/dist/index.d.ts +10 -0
  424. package/dist/index.js +13 -1
  425. package/dist/next/components/GlobalError.js +2 -2
  426. package/dist/next/routing/route-map.d.ts +2 -0
  427. package/dist/next/routing/route-map.js +1 -0
  428. package/dist/react/ErrorBoundary.js +2 -2
  429. package/dist/styles.css +2 -1
  430. package/dist/tailwind-utilities.css +1 -1
  431. package/dist/ui/DataTable.js +17 -16
  432. package/dist/ui/components/DateInput.js +2 -2
  433. package/dist/ui/components/DetailPageGallery.js +4 -1
  434. package/dist/ui/components/DetailPageTabs.js +6 -2
  435. package/dist/ui/components/ImageLightbox.js +5 -3
  436. package/dist/ui/components/Input.js +6 -3
  437. package/dist/ui/components/Layout.d.ts +4 -0
  438. package/dist/ui/components/Layout.js +1 -1
  439. package/dist/ui/components/Layout.style.css +1 -0
  440. package/dist/ui/components/ListingFilterDrawer.js +4 -1
  441. package/dist/ui/components/ListingLayout.js +9 -8
  442. package/dist/ui/components/ListingToolbar.js +5 -1
  443. package/dist/ui/components/PaginatedSelect.d.ts +1 -2
  444. package/dist/ui/components/PaginatedSelect.js +1 -2
  445. package/dist/ui/components/Radio.js +1 -1
  446. package/dist/ui/components/Select.js +2 -1
  447. package/dist/ui/components/Slider.js +1 -1
  448. package/dist/ui/components/VacationBanner.js +2 -1
  449. package/dist/ui/components/surface-tokens.d.ts +1 -0
  450. package/dist/ui/components/surface-tokens.js +1 -0
  451. package/package.json +11 -2
@@ -28,6 +28,7 @@ const DEFAULT_LIGHT_BG = {
28
28
  };
29
29
  const CLS_STAT_BOX = "flex flex-col items-center gap-1 p-2 bg-zinc-100 dark:bg-zinc-800 rounded-lg text-center";
30
30
  const CLS_STAT_LABEL = "text-xs text-zinc-500 dark:text-zinc-400";
31
+ const CLS_LOGOUT_BTN = "flex w-full items-center gap-3 rounded-lg px-3 py-2 text-sm text-red-600 transition-colors hover:bg-red-50 hover:text-red-700 dark:text-red-400 dark:hover:bg-red-950/30 dark:hover:text-red-300";
31
32
  const DEFAULT_DARK_BG = {
32
33
  type: "color",
33
34
  value: "#030712",
@@ -91,7 +92,7 @@ function SidebarContent({ sidebarItems, sidebarSections, sidebarPrimaryActions,
91
92
  action.variant === "outline"
92
93
  ? "border border-zinc-300 text-zinc-700 hover:bg-zinc-50 dark:border-slate-700 dark:text-zinc-100 dark:hover:bg-slate-800"
93
94
  : "bg-primary text-white hover:bg-primary-600 dark:bg-primary dark:hover:bg-primary-600 btn-glow",
94
- ].join(" "), children: action.label }, `${action.href}-${action.label}`))) })), isAuthenticated && (_jsx(CollapsibleNavGroup, { title: labels.sectionTitle, children: _jsxs(Ul, { className: "space-y-0.5", children: [_jsx(Li, { children: _jsx(TextLink, { href: profileHref, variant: "none", className: navItemClass, children: labels.profile }) }), userOrdersHref && (_jsx(Li, { children: _jsx(TextLink, { href: userOrdersHref, variant: "none", className: navItemClass, children: labels.orders }) })), userWishlistHref && (_jsx(Li, { children: _jsx(TextLink, { href: userWishlistHref, variant: "none", className: navItemClass, children: labels.wishlist }) })), userSettingsHref && (_jsx(Li, { children: _jsx(TextLink, { href: userSettingsHref, variant: "none", className: navItemClass, children: labels.settings }) }))] }) })), isAuthenticated && user?.stats && (_jsxs(Div, { className: "grid grid-cols-2 gap-2", children: [user.stats.totalOrders != null && (_jsxs(Div, { className: CLS_STAT_BOX, children: [_jsx(Text, { className: "text-lg font-bold text-zinc-900 dark:text-zinc-100 leading-none", children: user.stats.totalOrders }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Orders" })] })), user.stats.reviewsCount != null && (_jsxs(Div, { className: CLS_STAT_BOX, children: [_jsx(Text, { className: "text-lg font-bold text-zinc-900 dark:text-zinc-100 leading-none", children: user.stats.reviewsCount }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Reviews" })] })), user.stats.auctionsWon != null && (_jsxs(Div, { className: CLS_STAT_BOX, children: [_jsx(Text, { className: "text-lg font-bold text-zinc-900 dark:text-zinc-100 leading-none", children: user.stats.auctionsWon }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Auctions Won" })] })), user.stats.itemsSold != null && (_jsxs(Div, { className: CLS_STAT_BOX, children: [_jsx(Text, { className: "text-lg font-bold text-zinc-900 dark:text-zinc-100 leading-none", children: user.stats.itemsSold }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Items Sold" })] }))] })), isAuthenticated && isAdminOrSeller && (adminHref || resolvedStoreHref) && (_jsx(CollapsibleNavGroup, { title: labels.dashboardSectionTitle, children: _jsxs(Ul, { className: "space-y-0.5", children: [adminHref && role === "admin" && (_jsx(Li, { children: _jsx(TextLink, { href: adminHref, variant: "none", className: navItemClass, children: labels.adminDashboard }) })), resolvedStoreHref && isAdminOrSeller && (_jsx(Li, { children: _jsx(TextLink, { href: resolvedStoreHref, variant: "none", className: navItemClass, children: labels.storeDashboard }) }))] }) })), normalizedSections.map((section, sectionIndex) => (_jsx(CollapsibleSidebarSection, { section: section, navItemClass: navItemClass }, `sidebar-section-${sectionIndex}`))), (sidebarLocaleSlot || showThemeToggleInSidebar || (isAuthenticated && onLogout)) && (_jsxs(Div, { className: "border-t border-zinc-200 pt-4 space-y-3 dark:border-slate-800", children: [sidebarLocaleSlot, showThemeToggleInSidebar && (_jsxs("button", { type: "button", onClick: toggleTheme, className: "flex w-full items-center gap-3 rounded-lg px-3 py-2 text-sm text-zinc-700 transition-colors hover:bg-primary-50 hover:text-primary-800 dark:text-zinc-300 dark:hover:bg-slate-800 dark:hover:text-secondary-300", children: [_jsx("span", { "aria-hidden": "true", children: theme === "dark" ? "☀️" : "🌙" }), theme === "dark" ? "Light mode" : "Dark mode"] })), isAuthenticated && onLogout && (_jsx("button", { type: "button", onClick: () => { onLogout(); onAfterLogout(); }, className: "flex w-full items-center gap-3 rounded-lg px-3 py-2 text-sm text-red-600 transition-colors hover:bg-red-50 hover:text-red-700 dark:text-red-400 dark:hover:bg-red-950/30 dark:hover:text-red-300", children: labels.logout }))] }))] }));
95
+ ].join(" "), children: action.label }, `${action.href}-${action.label}`))) })), isAuthenticated && (_jsx(CollapsibleNavGroup, { title: labels.sectionTitle, children: _jsxs(Ul, { className: "space-y-0.5", children: [_jsx(Li, { children: _jsx(TextLink, { href: profileHref, variant: "none", className: navItemClass, children: labels.profile }) }), userOrdersHref && (_jsx(Li, { children: _jsx(TextLink, { href: userOrdersHref, variant: "none", className: navItemClass, children: labels.orders }) })), userWishlistHref && (_jsx(Li, { children: _jsx(TextLink, { href: userWishlistHref, variant: "none", className: navItemClass, children: labels.wishlist }) })), userSettingsHref && (_jsx(Li, { children: _jsx(TextLink, { href: userSettingsHref, variant: "none", className: navItemClass, children: labels.settings }) }))] }) })), isAuthenticated && user?.stats && (_jsxs(Div, { className: "grid grid-cols-2 gap-2", children: [user.stats.totalOrders != null && (_jsxs(Div, { className: CLS_STAT_BOX, children: [_jsx(Text, { className: "text-lg font-bold text-zinc-900 dark:text-zinc-100 leading-none", children: user.stats.totalOrders }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Orders" })] })), user.stats.reviewsCount != null && (_jsxs(Div, { className: CLS_STAT_BOX, children: [_jsx(Text, { className: "text-lg font-bold text-zinc-900 dark:text-zinc-100 leading-none", children: user.stats.reviewsCount }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Reviews" })] })), user.stats.auctionsWon != null && (_jsxs(Div, { className: CLS_STAT_BOX, children: [_jsx(Text, { className: "text-lg font-bold text-zinc-900 dark:text-zinc-100 leading-none", children: user.stats.auctionsWon }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Auctions Won" })] })), user.stats.itemsSold != null && (_jsxs(Div, { className: CLS_STAT_BOX, children: [_jsx(Text, { className: "text-lg font-bold text-zinc-900 dark:text-zinc-100 leading-none", children: user.stats.itemsSold }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Items Sold" })] }))] })), isAuthenticated && isAdminOrSeller && (adminHref || resolvedStoreHref) && (_jsx(CollapsibleNavGroup, { title: labels.dashboardSectionTitle, children: _jsxs(Ul, { className: "space-y-0.5", children: [adminHref && role === "admin" && (_jsx(Li, { children: _jsx(TextLink, { href: adminHref, variant: "none", className: navItemClass, children: labels.adminDashboard }) })), resolvedStoreHref && isAdminOrSeller && (_jsx(Li, { children: _jsx(TextLink, { href: resolvedStoreHref, variant: "none", className: navItemClass, children: labels.storeDashboard }) }))] }) })), normalizedSections.map((section, sectionIndex) => (_jsx(CollapsibleSidebarSection, { section: section, navItemClass: navItemClass }, `sidebar-section-${sectionIndex}`))), (sidebarLocaleSlot || showThemeToggleInSidebar || (isAuthenticated && onLogout)) && (_jsxs(Div, { className: "border-t border-zinc-200 pt-4 space-y-3 dark:border-slate-800", children: [sidebarLocaleSlot, showThemeToggleInSidebar && (_jsxs("button", { type: "button", onClick: toggleTheme, className: "flex w-full items-center gap-3 rounded-lg px-3 py-2 text-sm text-zinc-700 transition-colors hover:bg-primary-50 hover:text-primary-800 dark:text-zinc-300 dark:hover:bg-slate-800 dark:hover:text-secondary-300", children: [_jsx("span", { "aria-hidden": "true", children: theme === "dark" ? "☀️" : "🌙" }), theme === "dark" ? "Light mode" : "Dark mode"] })), isAuthenticated && onLogout && (_jsx("button", { type: "button", onClick: () => { onLogout(); onAfterLogout(); }, className: CLS_LOGOUT_BTN, children: labels.logout }))] }))] }));
95
96
  }
96
97
  // ─── Main component ────────────────────────────────────────────────────────────
97
98
  export function AppLayoutShell({ children, navItems, sidebarItems = [], sidebarSections, sidebarPrimaryActions, sidebarTitle = "Navigation", hiddenNavItems, user, brandName, brandShortName, siteLogoUrl, logoHref, promotionsHref, cartHref, wishlistHref, userId, profileHref, loginHref, registerHref, homeHref, shopHref, footer, searchSlot, searchSlotRenderer, titleBarNavSlot, titleBarNotificationSlot, titleBarDevSlot, titleBarPromoStripText, showThemeToggle = false, suppressDashboardNav = false, hideSidebarToggle = false, onLogout, adminHref, storeHref, sellerHref, userOrdersHref, userWishlistHref, userSettingsHref, sidebarLocaleSlot, showThemeToggleInSidebar = false, sidebarProfileLabels, eventBannerSlot, contentClassName, lightBackground = DEFAULT_LIGHT_BG, darkBackground = DEFAULT_DARK_BG, }) {
@@ -21,5 +21,5 @@ export function BackToTop({ threshold = 400, ariaLabel = "Back to top", classNam
21
21
  }
22
22
  /** SkipToMain — visually hidden link that becomes visible on focus for keyboard users. */
23
23
  export function SkipToMain({ mainId = "main-content" }) {
24
- return (_jsx(Link, { href: `#${mainId}`, className: "sr-only focus:not-sr-only focus:fixed focus:top-4 focus:left-4 focus:z-[100] focus:px-4 focus:py-2 focus:rounded-lg focus:bg-white dark:focus:bg-slate-900 focus:text-zinc-900 dark:focus:text-zinc-100 focus:shadow-lg focus:ring-2 focus:ring-primary-500 focus:outline-none text-sm font-medium", children: "Skip to main content" }));
24
+ return (_jsx(Link, { href: `#${mainId}`, className: "sr-only focus:not-sr-only focus:fixed focus:top-4 focus:left-4 focus:z-[var(--appkit-z-toast)] focus:px-4 focus:py-2 focus:rounded-lg focus:bg-white dark:focus:bg-slate-900 focus:text-zinc-900 dark:focus:text-zinc-100 focus:shadow-lg focus:ring-2 focus:ring-primary-500 focus:outline-none text-sm font-medium", children: "Skip to main content" }));
25
25
  }
@@ -1,42 +1,16 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- /**
4
- * BottomActions Component
5
- *
6
- * A fixed-bottom mobile action bar rendered **above** BottomNavbar (bottom-14).
7
- * Reads from `BottomActionsContext` — features register their actions via the
8
- * `useBottomActions` hook; this component just renders whatever is registered.
9
- *
10
- * Two modes:
11
- * - **Page mode** — shows registered page-level actions inline (Add to Cart,
12
- * Buy Now, Place Bid, Proceed to Checkout, etc.) with an optional info label.
13
- * - **Bulk mode** — activates when `bulk.selectedCount > 0`; shows:
14
- * • Selection count pill on the left (tap to deselect all)
15
- * • An upward-opening type-picker dropdown (middle, flex-1) — tap to
16
- * choose WHICH action to run; the chosen label is always visible.
17
- * • An "Apply" submit button on the right — executes the selected action,
18
- * styled with the selected action's variant (danger = red, etc.).
19
- *
20
- * Layout rules:
21
- * - Hidden on lg+ screens (`lg:hidden`) — desktop shows inline action panels.
22
- * - The bar slides up with a 300 ms ease-out transition; `pointer-events-none`
23
- * while off-screen.
24
- *
25
- * @component
26
- * @example
27
- * // Automatically rendered by LayoutClient — no manual usage required.
28
- * // Features use `useBottomActions` to register their actions.
29
- */
30
3
  import { useState, useRef, useEffect } from "react";
31
4
  import { X, ChevronUp, ChevronDown, Check } from "lucide-react";
32
5
  import { useBottomActionsContext } from "./BottomActionsContext";
33
6
  import { useClickOutside } from "../../react";
34
- import { Row, Span, Text, Button } from "../../ui";
7
+ import { Div, Row, Span, Text, Button } from "../../ui";
35
8
  // Token values inlined from @mohasinac/appkit/tokens
36
9
  const BOTTOM_NAV_BG = "bg-white/90 dark:bg-slate-950/90 backdrop-blur-md border-t border-zinc-200/80 dark:border-slate-800/80";
37
10
  const Z_BOTTOM_ACTIONS = "z-40";
38
11
  const BOTTOM_NAV_HEIGHT = "h-14";
39
12
  const FLEX_CENTER = "flex items-center justify-center";
13
+ const CLS_COUNT_BADGE = "bg-red-500 text-white";
40
14
  // ─── Sub-components ───────────────────────────────────────────────────────────
41
15
  function BulkPickerPanel({ bulkActions, selectedActionId, pickerOpen, onSelect, }) {
42
16
  return (_jsx("div", { role: "listbox", "aria-label": "Bulk actions", className: [
@@ -75,7 +49,7 @@ function PageActionsRow({ pageActions, dispatchAction, }) {
75
49
  isIconOnly ? "px-0 justify-center" : "",
76
50
  ]
77
51
  .filter(Boolean)
78
- .join(" "), children: [action.icon && (_jsx(Span, { className: ["flex-shrink-0", action.label ? "mr-1.5" : ""].join(" "), "aria-hidden": "true", children: action.icon })), action.label && _jsx(Span, { className: "truncate leading-none", children: action.label }), action.badge !== undefined && (_jsx(Span, { className: `absolute -top-1.5 -right-1.5 min-w-[18px] h-[18px] bg-red-500 text-white text-[10px] font-bold rounded-full ${FLEX_CENTER} px-1 pointer-events-none select-none`, "aria-hidden": "true", children: action.badge }))] }, action.id));
52
+ .join(" "), children: [action.icon && (_jsx(Span, { className: ["flex-shrink-0", action.label ? "mr-1.5" : ""].join(" "), "aria-hidden": "true", children: action.icon })), action.label && _jsx(Span, { className: "truncate leading-none", children: action.label }), action.badge !== undefined && (_jsx(Span, { className: `absolute -top-1.5 -right-1.5 min-w-[18px] h-[18px] ${CLS_COUNT_BADGE} text-[10px] font-bold rounded-full ${FLEX_CENTER} px-1 pointer-events-none select-none`, "aria-hidden": "true", children: action.badge }))] }, action.id));
79
53
  }) }));
80
54
  }
81
55
  export default function BottomActions() {
@@ -126,7 +100,7 @@ export default function BottomActions() {
126
100
  isVisible ? "translate-y-0" : "translate-y-full pointer-events-none",
127
101
  ]
128
102
  .filter(Boolean)
129
- .join(" "), "data-section": "bottomactions-div-401", children: [isBulkMode && (_jsx(BulkPickerPanel, { bulkActions: bulkActions, selectedActionId: selectedActionId, pickerOpen: pickerOpen, onSelect: (id) => { setSelectedActionId(id); setPickerOpen(false); } })), isBulkMode && (_jsx("div", { className: "h-[3px] w-full bg-gradient-to-r from-primary-600 via-secondary-400 to-primary-600 dark:from-primary-600 dark:via-primary-400 dark:to-primary-600" })), infoLabel && !isBulkMode && (_jsx("div", { className: "px-4 pt-2 pb-0 border-b border-zinc-100/80 dark:border-slate-800/80", "data-section": "bottomactions-div-403", children: _jsx(Text, { className: "text-xs font-semibold text-zinc-500 dark:text-zinc-400 leading-5 truncate", children: infoLabel }) })), _jsx(Row, { className: `gap-2 px-3 ${BOTTOM_NAV_HEIGHT}`, children: isBulkMode && bulk ? (_jsxs(_Fragment, { children: [_jsxs(Button, { type: "button", variant: "ghost", onClick: dispatchBulkClear, className: "inline-flex items-center gap-1.5 flex-shrink-0 bg-primary-50 hover:bg-primary-100 active:bg-primary-200 dark:bg-primary-950/30 dark:hover:bg-primary-900/50 text-primary-700 dark:text-primary-300 rounded-full pl-2 pr-3 h-8 border border-primary-200/70 dark:border-primary-800/50 transition-colors min-h-0", "aria-label": "Clear selection", children: [_jsx(X, { className: "w-3.5 h-3.5 flex-shrink-0", "aria-hidden": "true" }), _jsx(Span, { className: "text-xs font-semibold tabular-nums whitespace-nowrap leading-none", children: bulk.noun
103
+ .join(" "), "data-section": "bottomactions-div-401", children: [isBulkMode && (_jsx(BulkPickerPanel, { bulkActions: bulkActions, selectedActionId: selectedActionId, pickerOpen: pickerOpen, onSelect: (id) => { setSelectedActionId(id); setPickerOpen(false); } })), isBulkMode && (_jsx(Div, { className: "h-[3px] w-full bg-gradient-to-r from-primary-600 via-secondary-400 to-primary-600 dark:from-primary-600 dark:via-primary-400 dark:to-primary-600" })), infoLabel && !isBulkMode && (_jsx(Div, { className: "px-4 pt-2 pb-0 border-b border-zinc-100/80 dark:border-slate-800/80", children: _jsx(Text, { className: "text-xs font-semibold text-zinc-500 dark:text-zinc-400 leading-5 truncate", children: infoLabel }) })), _jsx(Row, { className: `gap-2 px-3 ${BOTTOM_NAV_HEIGHT}`, children: isBulkMode && bulk ? (_jsxs(_Fragment, { children: [_jsxs(Button, { type: "button", variant: "ghost", onClick: dispatchBulkClear, className: "inline-flex items-center gap-1.5 flex-shrink-0 bg-primary-50 hover:bg-primary-100 active:bg-primary-200 dark:bg-primary-950/30 dark:hover:bg-primary-900/50 text-primary-700 dark:text-primary-300 rounded-full pl-2 pr-3 h-8 border border-primary-200/70 dark:border-primary-800/50 transition-colors min-h-0", "aria-label": "Clear selection", children: [_jsx(X, { className: "w-3.5 h-3.5 flex-shrink-0", "aria-hidden": "true" }), _jsx(Span, { size: "xs", weight: "semibold", className: "tabular-nums whitespace-nowrap leading-none", children: bulk.noun
130
104
  ? `${bulk.selectedCount} ${bulk.noun}`
131
105
  : `${bulk.selectedCount} selected` })] }), bulkActions.length > 0 && (_jsxs(Button, { type: "button", variant: "ghost", onClick: () => setPickerOpen((o) => !o), "aria-haspopup": "listbox", "aria-expanded": pickerOpen, className: [
132
106
  "flex-1 min-w-0 h-10 flex items-center gap-2 px-3 rounded-lg border text-sm font-medium transition-colors",
@@ -1,39 +1,3 @@
1
- /**
2
- * BottomActionsContext
3
- *
4
- * Provides a context for registering page-level mobile action bars.
5
- * Features call `useBottomActions` to push actions; the `<BottomActions>`
6
- * layout component reads this context and renders the bar above BottomNavbar.
7
- *
8
- * Supports two modes:
9
- * - Page mode: primary page actions (Add to Cart, Buy Now, Place Bid, etc.)
10
- * - Bulk mode: activated when `bulk.selectedCount > 0` — shows selection
11
- * count + custom bulk action buttons (Delete, Archive, Export, etc.)
12
- *
13
- * @example — product detail page
14
- * ```tsx
15
- * useBottomActions({
16
- * actions: [
17
- * { id: "wishlist", icon: <Heart className="w-4 h-4" />, label: t("wishlist"), variant: "ghost", grow: false, onClick: handleWishlist },
18
- * { id: "cart", label: t("addToCart"), variant: "outline", onClick: handleAddToCart },
19
- * { id: "buy", label: t("buyNow"), variant: "primary", onClick: handleBuyNow },
20
- * ],
21
- * });
22
- * ```
23
- *
24
- * @example — admin listing with bulk select
25
- * ```tsx
26
- * useBottomActions({
27
- * bulk: {
28
- * selectedCount: selectedIds.length,
29
- * onClearSelection: () => setSelectedIds([]),
30
- * actions: [
31
- * { id: "delete", label: t("bulkDelete", { count: selectedIds.length }), variant: "danger", onClick: handleBulkDelete },
32
- * ],
33
- * },
34
- * });
35
- * ```
36
- */
37
1
  import React from "react";
38
2
  import type { ButtonProps } from "../../ui";
39
3
  export interface BottomAction {
@@ -1,41 +1,5 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- /**
4
- * BottomActionsContext
5
- *
6
- * Provides a context for registering page-level mobile action bars.
7
- * Features call `useBottomActions` to push actions; the `<BottomActions>`
8
- * layout component reads this context and renders the bar above BottomNavbar.
9
- *
10
- * Supports two modes:
11
- * - Page mode: primary page actions (Add to Cart, Buy Now, Place Bid, etc.)
12
- * - Bulk mode: activated when `bulk.selectedCount > 0` — shows selection
13
- * count + custom bulk action buttons (Delete, Archive, Export, etc.)
14
- *
15
- * @example — product detail page
16
- * ```tsx
17
- * useBottomActions({
18
- * actions: [
19
- * { id: "wishlist", icon: <Heart className="w-4 h-4" />, label: t("wishlist"), variant: "ghost", grow: false, onClick: handleWishlist },
20
- * { id: "cart", label: t("addToCart"), variant: "outline", onClick: handleAddToCart },
21
- * { id: "buy", label: t("buyNow"), variant: "primary", onClick: handleBuyNow },
22
- * ],
23
- * });
24
- * ```
25
- *
26
- * @example — admin listing with bulk select
27
- * ```tsx
28
- * useBottomActions({
29
- * bulk: {
30
- * selectedCount: selectedIds.length,
31
- * onClearSelection: () => setSelectedIds([]),
32
- * actions: [
33
- * { id: "delete", label: t("bulkDelete", { count: selectedIds.length }), variant: "danger", onClick: handleBulkDelete },
34
- * ],
35
- * },
36
- * });
37
- * ```
38
- */
39
3
  import { createContext, useCallback, useContext, useMemo, useRef, useState, } from "react";
40
4
  const EMPTY = { actions: [] };
41
5
  const BottomActionsContext = createContext(null);
@@ -23,5 +23,5 @@ export function BottomNavItem({ href, label, icon, badge, isActive = false, clas
23
23
  // Consumer projects may swap for next/link if preferred.
24
24
  return (_jsx(Li, { className: "flex-1", children: _jsxs("a", { href: href, "aria-label": label, "aria-current": isActive ? "page" : undefined, className: `relative flex flex-col items-center justify-center gap-0.5 h-full w-full min-h-[44px] transition-colors ${isActive
25
25
  ? "text-primary-600 dark:text-secondary-400"
26
- : "text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-200"}${className ? ` ${className}` : ""}`, children: [_jsxs(Span, { className: "relative", children: [icon, badge != null && badge > 0 && (_jsx(Span, { "aria-label": `${badge} items`, className: "absolute -top-1.5 -right-1.5 min-w-[16px] h-4 px-1 rounded-full text-[10px] font-bold bg-secondary-500 text-white flex items-center justify-center leading-none", children: badge > 99 ? "99+" : badge }))] }), _jsx(Span, { className: "text-[10px] font-medium leading-none", children: label })] }) }));
26
+ : "text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-200"}${className ? ` ${className}` : ""}`, children: [_jsxs(Span, { className: "relative", children: [icon, badge != null && badge > 0 && (_jsx(Span, { "aria-label": `${badge} items`, className: "absolute -top-1.5 -right-1.5 min-w-[16px] h-4 px-1 rounded-full text-[10px] font-bold bg-secondary-500 text-white flex items-center justify-center leading-none", children: badge > 99 ? "99+" : badge }))] }), _jsx(Span, { weight: "medium", className: "text-[10px] leading-none", children: label })] }) }));
27
27
  }
@@ -2,6 +2,9 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useCallback } from "react";
4
4
  import { Button, Div, Row, Span } from "../../ui";
5
+ const __O = {
6
+ yAuto: "overflow-y-auto",
7
+ };
5
8
  /**
6
9
  * BottomSheet — mobile-first drawer that slides up from the bottom.
7
10
  *
@@ -35,5 +38,5 @@ export function BottomSheet({ open, onClose, title, children, className, maxHeig
35
38
  }, [open, handleEscape]);
36
39
  if (!open)
37
40
  return null;
38
- return (_jsxs(Div, { className: "fixed inset-0 z-50 lg:hidden", role: "presentation", children: [_jsx(Div, { className: "absolute inset-0 bg-black/50 backdrop-blur-sm", "aria-hidden": "true", onClick: onClose }), _jsxs(Div, { role: "dialog", "aria-modal": "true", "aria-label": title, className: `absolute bottom-0 inset-x-0 flex flex-col rounded-t-2xl bg-white dark:bg-zinc-900 border-t border-zinc-200 dark:border-zinc-800 shadow-2xl ${maxHeight} animate-slide-up${className ? ` ${className}` : ""}`, children: [_jsxs(Row, { justify: "between", className: "px-4 py-3 border-b border-zinc-100 dark:border-zinc-800 shrink-0", children: [_jsx(Div, { className: "absolute top-2 left-1/2 -translate-x-1/2 w-10 h-1 rounded-full bg-zinc-300 dark:bg-zinc-600" }), title && (_jsx(Span, { className: "text-sm font-semibold text-zinc-800 dark:text-zinc-100 mt-2", children: title })), _jsx(Button, { type: "button", onClick: onClose, "aria-label": "Close", className: "ml-auto mt-2 p-1.5 rounded-lg text-zinc-500 hover:text-zinc-700 hover:bg-zinc-100 dark:text-zinc-400 dark:hover:text-zinc-200 dark:hover:bg-zinc-800 transition-colors min-h-[44px] min-w-[44px] flex items-center justify-center", children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), _jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) })] }), _jsx(Div, { className: "flex-1 overflow-y-auto overscroll-contain pb-[env(safe-area-inset-bottom)]", children: children })] })] }));
41
+ return (_jsxs(Div, { className: "fixed inset-0 z-50 lg:hidden", role: "presentation", children: [_jsx(Div, { className: "absolute inset-0 bg-black/50 backdrop-blur-sm", "aria-hidden": "true", onClick: onClose }), _jsxs(Div, { role: "dialog", "aria-modal": "true", "aria-label": title, className: `absolute bottom-0 inset-x-0 flex flex-col rounded-t-2xl bg-white dark:bg-zinc-900 border-t border-zinc-200 dark:border-zinc-800 shadow-2xl ${maxHeight} animate-slide-up${className ? ` ${className}` : ""}`, children: [_jsxs(Row, { justify: "between", className: "px-4 py-3 border-b border-zinc-100 dark:border-zinc-800 shrink-0", children: [_jsx(Div, { className: "absolute top-2 left-1/2 -translate-x-1/2 w-10 h-1 rounded-full bg-zinc-300 dark:bg-zinc-600" }), title && (_jsx(Span, { size: "sm", weight: "semibold", className: "text-zinc-800 dark:text-zinc-100 mt-2", children: title })), _jsx(Button, { type: "button", onClick: onClose, "aria-label": "Close", className: "ml-auto mt-2 p-1.5 rounded-lg text-zinc-500 hover:text-zinc-700 hover:bg-zinc-100 dark:text-zinc-400 dark:hover:text-zinc-200 dark:hover:bg-zinc-800 transition-colors min-h-[44px] min-w-[44px] flex items-center justify-center", children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), _jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) })] }), _jsx(Div, { className: `flex-1 ${__O.yAuto} overscroll-contain pb-[env(safe-area-inset-bottom)]`, children: children })] })] }));
39
42
  }
@@ -8,7 +8,7 @@ export function FooterLayout({ brandName, brandDescription, socialLinks, linkGro
8
8
  const [openGroups, setOpenGroups] = useState({});
9
9
  const toggleGroup = (idx) => setOpenGroups((prev) => ({ ...prev, [idx]: !prev[idx] }));
10
10
  const visibleTrustItems = trustBarItems.filter((item) => item.visible !== false);
11
- return (_jsxs(BlockFooter, { id: id, className: "bg-zinc-50 dark:bg-slate-950 border-t border-zinc-200 dark:border-slate-800", children: [showTrustBar && visibleTrustItems.length > 0 && (_jsx(Div, { className: "border-b border-zinc-100 dark:border-slate-800 py-8", children: _jsx(Div, { className: "container mx-auto px-4 sm:px-6 lg:px-8 max-w-[1920px]", children: _jsx(Row, { as: "ul", wrap: true, justify: "center", gap: "lg", className: "lg:gap-10", children: visibleTrustItems.map((item, i) => (_jsx(Li, { children: _jsxs(Row, { gap: "sm", className: "text-sm min-w-[160px]", children: [_jsx(Span, { className: "flex-shrink-0 text-primary-600 dark:text-secondary-400 w-5 h-5", children: item.icon }), _jsxs(Span, { children: [_jsx(Span, { className: "font-bold text-zinc-900 dark:text-zinc-100 block text-sm", children: item.label }), item.subtitle && (_jsx(Span, { className: "text-zinc-500 dark:text-zinc-400 text-xs block", children: item.subtitle }))] })] }) }, item.id ?? String(i)))) }) }) })), _jsxs(Div, { className: "container mx-auto px-4 sm:px-6 lg:px-8 max-w-[1920px] py-10 lg:py-14", children: [_jsxs(Div, { className: "grid grid-cols-1 lg:grid-cols-5 gap-10 lg:gap-16", children: [_jsxs(Div, { className: "lg:col-span-2 space-y-4", children: [_jsx(Heading, { level: 5, className: "text-zinc-900 dark:text-zinc-50 font-bold text-xl", children: brandName }), _jsx(Text, { className: "text-sm text-zinc-600 dark:text-zinc-400 leading-relaxed max-w-sm", children: brandDescription }), socialLinks.length > 0 && (_jsx(Row, { as: Ul, gap: "sm", children: socialLinks.map((link) => (_jsx(Li, { children: _jsx(Link, { href: link.href, "aria-label": link.ariaLabel, target: "_blank", rel: "noopener noreferrer", className: "flex items-center justify-center w-9 h-9 rounded-full border border-zinc-200 dark:border-slate-700 text-zinc-500 dark:text-zinc-400 hover:text-primary dark:hover:text-secondary hover:border-primary/40 dark:hover:border-secondary/40 transition-colors", children: link.icon }) }, link.platform))) })), newsletterEnabled && newsletterSlot && (_jsx(Div, { className: "pt-2", children: newsletterSlot }))] }), _jsx(Div, { className: `lg:col-span-3 grid grid-cols-1 gap-0 lg:gap-8 ${linkGroups.length <= 3 ? "lg:grid-cols-3" :
11
+ return (_jsxs(BlockFooter, { id: id, className: "bg-zinc-50 dark:bg-slate-950 border-t border-zinc-200 dark:border-slate-800", children: [showTrustBar && visibleTrustItems.length > 0 && (_jsx(Div, { className: "border-b border-zinc-100 dark:border-slate-800 py-8", children: _jsx(Div, { className: "container mx-auto px-4 sm:px-6 lg:px-8 max-w-[1920px]", children: _jsx(Row, { as: "ul", wrap: true, justify: "center", gap: "lg", className: "lg:gap-10", children: visibleTrustItems.map((item, i) => (_jsx(Li, { children: _jsxs(Row, { gap: "sm", className: "text-sm min-w-[160px]", children: [_jsx(Span, { className: "flex-shrink-0 text-primary-600 dark:text-secondary-400 w-5 h-5", children: item.icon }), _jsxs(Span, { children: [_jsx(Span, { size: "sm", weight: "bold", className: "text-zinc-900 dark:text-zinc-100 block", children: item.label }), item.subtitle && (_jsx(Span, { size: "xs", className: "text-zinc-500 dark:text-zinc-400 block", children: item.subtitle }))] })] }) }, item.id ?? String(i)))) }) }) })), _jsxs(Div, { className: "container mx-auto px-4 sm:px-6 lg:px-8 max-w-[1920px] py-10 lg:py-14", children: [_jsxs(Div, { className: "grid grid-cols-1 lg:grid-cols-5 gap-10 lg:gap-16", children: [_jsxs(Div, { className: "lg:col-span-2 space-y-4", children: [_jsx(Heading, { level: 5, className: "text-zinc-900 dark:text-zinc-50 font-bold text-xl", children: brandName }), _jsx(Text, { className: "text-sm text-zinc-600 dark:text-zinc-400 leading-relaxed max-w-sm", children: brandDescription }), socialLinks.length > 0 && (_jsx(Row, { as: Ul, gap: "sm", children: socialLinks.map((link) => (_jsx(Li, { children: _jsx(Link, { href: link.href, "aria-label": link.ariaLabel, target: "_blank", rel: "noopener noreferrer", className: "flex items-center justify-center w-9 h-9 rounded-full border border-zinc-200 dark:border-slate-700 text-zinc-500 dark:text-zinc-400 hover:text-primary dark:hover:text-secondary hover:border-primary/40 dark:hover:border-secondary/40 transition-colors", children: link.icon }) }, link.platform))) })), newsletterEnabled && newsletterSlot && (_jsx(Div, { className: "pt-2", children: newsletterSlot }))] }), _jsx(Div, { className: `lg:col-span-3 grid grid-cols-1 gap-0 lg:gap-8 ${linkGroups.length <= 3 ? "lg:grid-cols-3" :
12
12
  linkGroups.length === 4 ? "lg:grid-cols-4" :
13
13
  "lg:grid-cols-5"}`, children: linkGroups.map((group, idx) => (_jsxs(Div, { children: [_jsxs(Button, { type: "button", variant: "ghost", onClick: () => toggleGroup(idx), className: "flex w-full items-center justify-between border-b border-zinc-200 py-3 text-left text-sm font-semibold text-zinc-800 transition-colors hover:text-zinc-950 dark:border-slate-800 dark:text-zinc-100 dark:hover:text-white lg:hidden", "aria-expanded": !!openGroups[idx], children: [group.heading, _jsx(ChevronDown, { className: `w-4 h-4 transition-transform duration-200 ${openGroups[idx] ? "rotate-180" : ""}` })] }), _jsx(Ul, { className: `lg:hidden overflow-hidden transition-all duration-200 ${openGroups[idx] ? "max-h-96 py-3" : "max-h-0"} space-y-2.5`, children: group.links.map((link) => (_jsx(Li, { children: _jsx(Link, { href: link.href, className: "text-sm text-zinc-500 dark:text-zinc-400 hover:text-primary dark:hover:text-secondary transition-colors", children: link.label }) }, link.href))) }), _jsxs(Div, { className: "hidden lg:block", children: [_jsx(Text, { className: "text-xs font-semibold uppercase tracking-wider text-zinc-500 dark:text-zinc-400 mb-3", children: group.heading }), _jsx(Ul, { className: "space-y-2.5", children: group.links.map((link) => (_jsx(Li, { children: _jsx(Link, { href: link.href, className: "text-sm text-zinc-500 dark:text-zinc-400 hover:text-primary dark:hover:text-secondary transition-colors", children: link.label }) }, link.href))) })] })] }, idx))) })] }), _jsxs(Div, { className: "mt-10 pt-6 border-t border-zinc-200 dark:border-slate-800 flex flex-col sm:flex-row items-center justify-between gap-3 text-xs text-zinc-600 dark:text-zinc-400", children: [_jsx(Text, { className: "text-xs text-zinc-600 dark:text-zinc-400", children: copyrightText }), bottomLinks.length > 0 && (_jsx("nav", { "aria-label": "Site utilities", children: _jsx(Ul, { className: "flex flex-wrap items-center gap-x-4 gap-y-1 justify-center", children: bottomLinks.map((link) => (_jsx(Li, { children: _jsx(Link, { href: link.href, className: "text-xs text-zinc-500 dark:text-zinc-400 hover:text-primary dark:hover:text-secondary transition-colors underline-offset-2 hover:underline", children: link.label }) }, link.href))) }) })), madeInText && (_jsx(Text, { className: "text-xs text-zinc-600 dark:text-zinc-400", children: madeInText }))] })] })] }));
14
14
  }
@@ -3,6 +3,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useRef, useState, useEffect, useCallback } from "react";
4
4
  import Link from "next/link";
5
5
  import { Div, Li, Nav, Span, Ul } from "../../ui";
6
+ const __O = {
7
+ hidden: "overflow-hidden",
8
+ };
6
9
  function DefaultNavItem({ item, isActive, }) {
7
10
  const activeClasses = item.highlighted
8
11
  ? "border border-primary-400/40 dark:border-secondary-400/30 text-primary-700 dark:text-secondary-400 bg-primary-50/80 dark:bg-secondary-900/30 px-3 transition-colors duration-150"
@@ -48,5 +51,5 @@ export function NavbarLayout({ items, activeHref, id = "main-navbar", ariaLabel
48
51
  if (inline) {
49
52
  return (_jsx(Ul, { "aria-label": ariaLabel, className: "hidden xl:flex items-center gap-0.5 xl:gap-1", children: items.map((item) => (_jsx(Li, { children: renderItem ? (renderItem(item, activeHref === item.href)) : (_jsx(DefaultNavItem, { item: item, isActive: activeHref === item.href })) }, item.href))) }));
50
53
  }
51
- return (_jsx(Nav, { id: id, "aria-label": ariaLabel, className: "hidden lg:block bg-white/95 dark:bg-slate-950/95 backdrop-blur-md border-b border-zinc-100 dark:border-slate-800", children: _jsxs(Div, { className: "container mx-auto px-4 sm:px-6 lg:px-8 max-w-[1920px] flex items-center h-10", children: [_jsxs(Div, { className: "relative flex-1 overflow-hidden", children: [canScrollLeft && (_jsx("button", { type: "button", onClick: () => scroll("left"), "aria-label": "Scroll navigation left", className: `${chevronBtn} left-0 bg-gradient-to-r`, children: _jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) }) })), _jsx("ul", { ref: scrollRef, className: "flex items-center gap-0.5 lg:gap-1 overflow-x-auto [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]", children: items.map((item) => (_jsx("li", { className: "shrink-0", children: renderItem ? (renderItem(item, activeHref === item.href)) : (_jsx(DefaultNavItem, { item: item, isActive: activeHref === item.href })) }, item.href))) }), canScrollRight && (_jsx("button", { type: "button", onClick: () => scroll("right"), "aria-label": "Scroll navigation right", className: `${chevronBtn} right-0 bg-gradient-to-l`, children: _jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) }) }))] }), rightSlot && _jsx(Div, { className: "shrink-0 ml-2", children: rightSlot })] }) }));
54
+ return (_jsx(Nav, { id: id, "aria-label": ariaLabel, className: "hidden lg:block bg-white/95 dark:bg-slate-950/95 backdrop-blur-md border-b border-zinc-100 dark:border-slate-800", children: _jsxs(Div, { className: "container mx-auto px-4 sm:px-6 lg:px-8 max-w-[1920px] flex items-center h-10", children: [_jsxs(Div, { className: `relative flex-1 ${__O.hidden}`, children: [canScrollLeft && (_jsx("button", { type: "button", onClick: () => scroll("left"), "aria-label": "Scroll navigation left", className: `${chevronBtn} left-0 bg-gradient-to-r`, children: _jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) }) })), _jsx("ul", { ref: scrollRef, className: "flex items-center gap-0.5 lg:gap-1 overflow-x-auto [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]", children: items.map((item) => (_jsx("li", { className: "shrink-0", children: renderItem ? (renderItem(item, activeHref === item.href)) : (_jsx(DefaultNavItem, { item: item, isActive: activeHref === item.href })) }, item.href))) }), canScrollRight && (_jsx("button", { type: "button", onClick: () => scroll("right"), "aria-label": "Scroll navigation right", className: `${chevronBtn} right-0 bg-gradient-to-l`, children: _jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) }) }))] }), rightSlot && _jsx(Div, { className: "shrink-0 ml-2", children: rightSlot })] }) }));
52
55
  }
@@ -1,6 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { forwardRef } from "react";
3
3
  import { Aside, Div } from "../../ui";
4
+ const __O = {
5
+ yAuto: "overflow-y-auto",
6
+ };
4
7
  /**
5
8
  * SidebarLayout — generic slide-out sidebar shell.
6
9
  *
@@ -14,7 +17,7 @@ import { Aside, Div } from "../../ui";
14
17
  * to the rendered `aside` element.
15
18
  */
16
19
  export const SidebarLayout = forwardRef(function SidebarLayout({ isOpen, ariaLabel, onClose, header, children, id = "secondary-sidebar" }, ref) {
17
- return (_jsxs(_Fragment, { children: [isOpen && (_jsx(Div, { className: "fixed inset-0 bg-black/40 backdrop-blur-[2px] z-[45] transition-opacity duration-300", onClick: onClose, "aria-hidden": "true" })), _jsxs(Aside, { ref: ref, id: id, "aria-label": ariaLabel, className: `
20
+ return (_jsxs(_Fragment, { children: [isOpen && (_jsx(Div, { className: "fixed inset-0 bg-black/40 backdrop-blur-[2px] z-[var(--appkit-z-overlay)] transition-opacity duration-300", onClick: onClose, "aria-hidden": "true" })), _jsxs(Aside, { ref: ref, id: id, "aria-label": ariaLabel, className: `
18
21
  fixed inset-y-0 right-0
19
22
  w-80
20
23
  bg-white dark:bg-slate-900 border-l border-zinc-200 dark:border-slate-800
@@ -23,6 +26,6 @@ export const SidebarLayout = forwardRef(function SidebarLayout({ isOpen, ariaLab
23
26
  z-50
24
27
  ${isOpen ? "translate-x-0" : "translate-x-full"}
25
28
  flex flex-col
26
- `, children: [_jsx(Div, { className: "flex-shrink-0 px-6 py-5 border-b border-zinc-200 dark:border-slate-800 bg-zinc-50 dark:bg-slate-900/80", children: header }), _jsx(Div, { className: "flex-1 overflow-y-auto scrollbar-thin px-6 py-4", children: children })] })] }));
29
+ `, children: [_jsx(Div, { className: "flex-shrink-0 px-6 py-5 border-b border-zinc-200 dark:border-slate-800 bg-zinc-50 dark:bg-slate-900/80", children: header }), _jsx(Div, { className: `flex-1 ${__O.yAuto} scrollbar-thin px-6 py-4`, children: children })] })] }));
27
30
  });
28
31
  SidebarLayout.displayName = "SidebarLayout";
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { FilterFacetSection } from "../../filters/FilterFacetSection";
4
4
  import { AsyncFacetSection } from "../../filters/AsyncFacetSection";
5
5
  import { RangeFilter } from "../../filters/RangeFilter";
6
- import { Div } from "../../../ui";
6
+ import { Div, Label } from "../../../ui";
7
7
  const SEX_OPTIONS = [
8
8
  { value: "male", label: "Male" },
9
9
  { value: "female", label: "Female" },
@@ -20,5 +20,5 @@ export function LiveItemFilters({ table, categoryOptions = [], loadCategoryOptio
20
20
  : [];
21
21
  const selectedSex = table.get("liveSex") ? [table.get("liveSex")] : [];
22
22
  const selectedTransport = table.get("liveTransportMethod") ? [table.get("liveTransportMethod")] : [];
23
- return (_jsxs(Div, { children: [loadCategoryOptions ? (_jsx(AsyncFacetSection, { title: "Category", loadOptions: loadCategoryOptions, selected: selectedCategories, onChange: (vals) => table.set("category", vals.join("|")), defaultCollapsed: false })) : categoryOptions.length > 0 ? (_jsx(FilterFacetSection, { title: "Category", options: categoryOptions, selected: selectedCategories, onChange: (vals) => table.set("category", vals.join("|")), searchable: true, defaultCollapsed: categoryOptions.length > 6 })) : null, _jsxs("div", { className: "border-t border-[var(--appkit-color-border)] pt-4 mt-4", children: [_jsx("label", { className: "block text-sm font-medium text-[var(--appkit-color-text)] mb-2", children: "Species / Animal" }), _jsx("input", { type: "text", value: table.get("species") || "", onChange: (e) => table.set("species", e.target.value), placeholder: "e.g. Axolotl, Parrot", className: "w-full rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-3 py-2 text-sm text-[var(--appkit-color-text)] placeholder-[var(--appkit-color-text-faint)] focus:outline-none focus:ring-2 focus:ring-[var(--appkit-color-primary)]" })] }), _jsxs("div", { className: "border-t border-[var(--appkit-color-border)] pt-4 mt-4", children: [_jsx("label", { className: "block text-sm font-medium text-[var(--appkit-color-text)] mb-2", children: "Jurisdiction (state/UT)" }), _jsx("input", { type: "text", value: table.get("jurisdiction") || "", onChange: (e) => table.set("jurisdiction", e.target.value), placeholder: "e.g. Maharashtra", className: "w-full rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-3 py-2 text-sm text-[var(--appkit-color-text)] placeholder-[var(--appkit-color-text-faint)] focus:outline-none focus:ring-2 focus:ring-[var(--appkit-color-primary)]" })] }), _jsx(FilterFacetSection, { title: "Sex", options: SEX_OPTIONS, selected: selectedSex, onChange: (vals) => table.set("liveSex", vals[0] ?? ""), searchable: false, selectionMode: "single", defaultCollapsed: false }), _jsx(FilterFacetSection, { title: "Transport Method", options: TRANSPORT_OPTIONS, selected: selectedTransport, onChange: (vals) => table.set("liveTransportMethod", vals[0] ?? ""), searchable: false, selectionMode: "single", defaultCollapsed: false }), _jsx(RangeFilter, { title: "Price", minValue: table.get("minPrice"), maxValue: table.get("maxPrice"), onMinChange: (v) => table.set("minPrice", v), onMaxChange: (v) => table.set("maxPrice", v), prefix: currencyPrefix, showSlider: true, minBound: 0, maxBound: 200000, step: 100, minPlaceholder: "Min price", maxPlaceholder: "Max price", defaultCollapsed: false })] }));
23
+ return (_jsxs(Div, { children: [loadCategoryOptions ? (_jsx(AsyncFacetSection, { title: "Category", loadOptions: loadCategoryOptions, selected: selectedCategories, onChange: (vals) => table.set("category", vals.join("|")), defaultCollapsed: false })) : categoryOptions.length > 0 ? (_jsx(FilterFacetSection, { title: "Category", options: categoryOptions, selected: selectedCategories, onChange: (vals) => table.set("category", vals.join("|")), searchable: true, defaultCollapsed: categoryOptions.length > 6 })) : null, _jsxs(Div, { className: "border-t border-[var(--appkit-color-border)] pt-4 mt-4", children: [_jsx(Label, { className: "block text-sm font-medium text-[var(--appkit-color-text)] mb-2", children: "Species / Animal" }), _jsx("input", { type: "text", value: table.get("species") || "", onChange: (e) => table.set("species", e.target.value), placeholder: "e.g. Axolotl, Parrot", className: "w-full rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-3 py-2 text-sm text-[var(--appkit-color-text)] placeholder-[var(--appkit-color-text-faint)] focus:outline-none focus:ring-2 focus:ring-[var(--appkit-color-primary)]" })] }), _jsxs(Div, { className: "border-t border-[var(--appkit-color-border)] pt-4 mt-4", children: [_jsx(Label, { className: "block text-sm font-medium text-[var(--appkit-color-text)] mb-2", children: "Jurisdiction (state/UT)" }), _jsx("input", { type: "text", value: table.get("jurisdiction") || "", onChange: (e) => table.set("jurisdiction", e.target.value), placeholder: "e.g. Maharashtra", className: "w-full rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-3 py-2 text-sm text-[var(--appkit-color-text)] placeholder-[var(--appkit-color-text-faint)] focus:outline-none focus:ring-2 focus:ring-[var(--appkit-color-primary)]" })] }), _jsx(FilterFacetSection, { title: "Sex", options: SEX_OPTIONS, selected: selectedSex, onChange: (vals) => table.set("liveSex", vals[0] ?? ""), searchable: false, selectionMode: "single", defaultCollapsed: false }), _jsx(FilterFacetSection, { title: "Transport Method", options: TRANSPORT_OPTIONS, selected: selectedTransport, onChange: (vals) => table.set("liveTransportMethod", vals[0] ?? ""), searchable: false, selectionMode: "single", defaultCollapsed: false }), _jsx(RangeFilter, { title: "Price", minValue: table.get("minPrice"), maxValue: table.get("maxPrice"), onMinChange: (v) => table.set("minPrice", v), onMaxChange: (v) => table.set("maxPrice", v), prefix: currencyPrefix, showSlider: true, minBound: 0, maxBound: 200000, step: 100, minPlaceholder: "Min price", maxPlaceholder: "Max price", defaultCollapsed: false })] }));
24
24
  }
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useCallback } from "react";
4
4
  import { useUrlTable } from "../../../react/hooks/useUrlTable";
5
5
  import { useProducts } from "../../products/hooks/useProducts";
6
- import { BulkActionBar, FilterDrawer, ListingToolbar, LoginRequiredModal, Pagination, Text, useToast } from "../../../ui";
6
+ import { BulkActionBar, Div, FilterDrawer, ListingToolbar, LoginRequiredModal, Pagination, Text, useToast } from "../../../ui";
7
7
  import { usePendingTable } from "../../../react/hooks/usePendingTable";
8
8
  import { useAuthGate } from "../../../react/hooks/useAuthGate";
9
9
  import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
@@ -18,6 +18,12 @@ import { InteractiveProductCard } from "../../products/components/InteractivePro
18
18
  import { LiveItemFilters } from "./LiveItemFilters";
19
19
  import { ACTION_ID } from "../../products/constants/action-defs";
20
20
  import { useBottomActions } from "../../layout";
21
+ const __P = {
22
+ p3: "p-3",
23
+ };
24
+ const __O = {
25
+ hidden: "overflow-hidden",
26
+ };
21
27
  const DEFAULT_SORT = sortBy(PRODUCT_FIELDS.CREATED_AT);
22
28
  const SORT_OPTIONS = [
23
29
  { value: sortBy(PRODUCT_FIELDS.CREATED_AT), label: "Newest First" },
@@ -103,7 +109,7 @@ export function LiveItemsIndexListing({ initialData }) {
103
109
  }
104
110
  }
105
111
  useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [] } } : {});
106
- return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: filterActiveCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search live items\u2026", onSearchChange: setSearchInput, onSearchCommit: commitSearch, onSearchKeyDown: (e) => { if (e.key === "Enter")
112
+ return (_jsxs(Div, { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: filterActiveCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search live items\u2026", onSearchChange: setSearchInput, onSearchCommit: commitSearch, onSearchKeyDown: (e) => { if (e.key === "Enter")
107
113
  commitSearch(); }, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, view: view, onViewChange: (v) => { if (v !== "table")
108
- setView(v); }, onResetAll: resetAll, hasActiveState: hasActiveState, bulkMode: selection.isSelecting, bulkSelectedCount: selection.selectedCount, bulkTotalCount: products.length, onBulkSelectAll: selection.toggleAll, onBulkClear: selection.clearSelection }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [] }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: page, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsx("div", { className: "py-6", children: isLoading ? (_jsx("div", { className: gridClass, children: Array.from({ length: 10 }).map((_, i) => (_jsxs("div", { className: "rounded-xl border border-zinc-100 dark:border-slate-700 overflow-hidden animate-pulse", children: [_jsx("div", { className: "aspect-square bg-zinc-200 dark:bg-slate-700" }), _jsxs("div", { className: "p-3 space-y-2", children: [_jsx("div", { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-3/4" }), _jsx("div", { className: "h-4 bg-zinc-200 dark:bg-slate-700 rounded w-1/3" })] })] }, i))) })) : products.length === 0 ? (_jsx(Text, { className: "py-12 text-center text-sm text-zinc-500 dark:text-zinc-400", children: "No live item listings found." })) : (_jsx("div", { className: view === "list" ? "flex flex-col divide-y divide-zinc-100 dark:divide-zinc-800 rounded-xl border border-zinc-100 dark:border-zinc-800" : gridClass, children: products.map((product) => (_jsx(InteractiveProductCard, { product: product, href: String(ROUTES.PUBLIC.LIVE_DETAIL(product.id)), variant: view === "list" ? "list" : "grid", isWishlisted: wishlistActions.isWishlisted(product.id), onToggleWishlist: handleToggleWishlist, selectable: selection.isSelecting, isSelected: selection.isSelected(product.id), onSelect: (id) => selection.toggle(id) }, product.id))) })) }), _jsx(FilterDrawer, { open: filterOpen, onOpen: openFilters, onClose: () => setFilterOpen(false), onApply: applyFilters, onReset: onFilterClear, activeCount: filterActiveCount, hideTrigger: true, children: _jsx(LiveItemFilters, { table: pendingTable, categoryOptions: categoryOptions }) }), _jsx(LoginRequiredModal, { isOpen: modalOpen, onClose: closeModal, message: modalMessage })] }));
114
+ setView(v); }, onResetAll: resetAll, hasActiveState: hasActiveState, bulkMode: selection.isSelecting, bulkSelectedCount: selection.selectedCount, bulkTotalCount: products.length, onBulkSelectAll: selection.toggleAll, onBulkClear: selection.clearSelection }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [] }), totalPages > 1 && (_jsx(Div, { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: page, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsx(Div, { className: "py-6", children: isLoading ? (_jsx(Div, { className: gridClass, children: Array.from({ length: 10 }).map((_, i) => (_jsxs(Div, { className: `rounded-xl border border-zinc-100 dark:border-slate-700 ${__O.hidden} animate-pulse`, children: [_jsx(Div, { className: "aspect-square bg-zinc-200 dark:bg-slate-700" }), _jsxs(Div, { className: `${__P.p3} space-y-2`, children: [_jsx(Div, { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-3/4" }), _jsx(Div, { className: "h-4 bg-zinc-200 dark:bg-slate-700 rounded w-1/3" })] })] }, i))) })) : products.length === 0 ? (_jsx(Text, { className: "py-12 text-center text-sm text-zinc-500 dark:text-zinc-400", children: "No live item listings found." })) : (_jsx(Div, { className: view === "list" ? "flex flex-col divide-y divide-zinc-100 dark:divide-zinc-800 rounded-xl border border-zinc-100 dark:border-zinc-800" : gridClass, children: products.map((product) => (_jsx(InteractiveProductCard, { product: product, href: String(ROUTES.PUBLIC.LIVE_DETAIL(product.id)), variant: view === "list" ? "list" : "grid", isWishlisted: wishlistActions.isWishlisted(product.id), onToggleWishlist: handleToggleWishlist, selectable: selection.isSelecting, isSelected: selection.isSelected(product.id), onSelect: (id) => selection.toggle(id) }, product.id))) })) }), _jsx(FilterDrawer, { open: filterOpen, onOpen: openFilters, onClose: () => setFilterOpen(false), onApply: applyFilters, onReset: onFilterClear, activeCount: filterActiveCount, hideTrigger: true, children: _jsx(LiveItemFilters, { table: pendingTable, categoryOptions: categoryOptions }) }), _jsx(LoginRequiredModal, { isOpen: modalOpen, onClose: closeModal, message: modalMessage })] }));
109
115
  }
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { sieveFilter, SIEVE_OP } from "@mohasinac/appkit";
2
3
  import { productRepository } from "../../../repositories";
3
4
  import { Container, Heading, Main, Section } from "../../../ui";
4
5
  import { AdSlot } from "../../homepage/components/AdSlot";
@@ -16,18 +17,18 @@ function buildLiveFilters(params) {
16
17
  const minPrice = sp(params, "minPrice");
17
18
  const maxPrice = sp(params, "maxPrice");
18
19
  if (minPrice)
19
- parts.push(`price>=${minPrice}`);
20
+ parts.push(sieveFilter("price", SIEVE_OP.GTE, minPrice));
20
21
  if (maxPrice)
21
- parts.push(`price<=${maxPrice}`);
22
+ parts.push(sieveFilter("price", SIEVE_OP.LTE, maxPrice));
22
23
  const species = sp(params, "species");
23
24
  if (species)
24
- parts.push(`liveSpecies==${species}`);
25
+ parts.push(sieveFilter("liveSpecies", SIEVE_OP.EQ, species));
25
26
  const liveSex = sp(params, "liveSex");
26
27
  if (liveSex)
27
- parts.push(`liveSex==${liveSex}`);
28
+ parts.push(sieveFilter("liveSex", SIEVE_OP.EQ, liveSex));
28
29
  const transport = sp(params, "liveTransportMethod");
29
30
  if (transport)
30
- parts.push(`liveTransportMethod==${transport}`);
31
+ parts.push(sieveFilter("liveTransportMethod", SIEVE_OP.EQ, transport));
31
32
  return parts.join(",");
32
33
  }
33
34
  export async function LiveItemsListView({ searchParams = {} }) {
@@ -1,8 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Div, Span, Text } from "../../../ui";
3
+ const CLS_COIN_PILL = "inline-flex items-center gap-1 rounded-full bg-amber-100 px-2 py-0.5 text-xs font-semibold text-amber-800";
4
+ const CLS_COIN_TOTAL = "text-3xl font-bold text-amber-600";
3
5
  export function CoinsBadge({ coins, className }) {
4
- return (_jsxs(Span, { className: `inline-flex items-center gap-1 rounded-full bg-amber-100 px-2 py-0.5 text-xs font-semibold text-amber-800 ${className ?? ""}`, children: [_jsx(Span, { "aria-hidden": "true", children: "\uD83E\uDE99" }), coins.toLocaleString()] }));
6
+ return (_jsxs(Span, { className: `${CLS_COIN_PILL} ${className ?? ""}`, children: [_jsx(Span, { "aria-hidden": "true", children: "\uD83E\uDE99" }), coins.toLocaleString()] }));
5
7
  }
6
8
  export function CoinsDisplay({ coins, label = "HC Coins" }) {
7
- return (_jsxs(Div, { className: "flex flex-col items-center gap-1", children: [_jsx(Text, { className: "text-3xl font-bold text-amber-600", children: coins.toLocaleString() }), _jsx(Text, { className: "text-sm text-gray-500", children: label })] }));
9
+ return (_jsxs(Div, { className: "flex flex-col items-center gap-1", children: [_jsx(Text, { className: CLS_COIN_TOTAL, children: coins.toLocaleString() }), _jsx(Text, { className: "text-sm text-gray-500", children: label })] }));
8
10
  }
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { useEffect, useRef, useState } from "react";
4
- import { Alert, Button, Input, Progress, Text, useToast } from "../../ui";
4
+ import { Alert, Button, Div, Input, Progress, Text, useToast } from "../../ui";
5
5
  import { useMediaUpload } from "./hooks/useMedia";
6
6
  import { ImageCropModal } from "./modals/ImageCropModal";
7
7
  import { AvatarDisplay } from "../../ui/components/AvatarDisplay";
@@ -106,6 +106,6 @@ export function AvatarUpload({ currentPhotoURL, currentCropData, userId, display
106
106
  fileInputRef.current.value = "";
107
107
  };
108
108
  const hasPending = pendingCropData !== null && pendingUploadFile !== null;
109
- return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "space-y-4", "data-section": "avatarupload-div-404", children: [_jsxs("div", { className: "flex items-start gap-6", "data-section": "avatarupload-div-405", children: [_jsx("div", { className: "shrink-0", "data-section": "avatarupload-div-406", children: _jsx(AvatarDisplay, { cropData: hasPending ? pendingCropData : cropData, size: "2xl", className: `border-4 ${hasPending ? "border-primary/60 ring-2 ring-primary/20" : "border-zinc-200 dark:border-slate-700"}`, displayName: displayName }) }), _jsxs("div", { className: "flex-1 space-y-3", "data-section": "avatarupload-div-407", children: [_jsx(Text, { variant: "secondary", className: "text-xs", children: "JPG, PNG, WEBP or GIF up to 10MB." }), isUploading ? (_jsx(Progress, { value: 50, variant: "primary", size: "sm", label: t.uploading })) : null, hasPending && !isUploading ? (_jsxs("div", { className: "space-y-2", "data-section": "avatarupload-div-408", children: [_jsx(Text, { variant: "secondary", className: "text-xs text-primary", children: t.readyToSave }), _jsxs("div", { className: "flex gap-3", "data-section": "avatarupload-div-409", children: [_jsx(Button, { type: "button", onClick: handleConfirmSave, size: "sm", children: t.saveAvatar }), _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: handleCancelPending, children: t.cancelChange })] })] })) : null, !hasPending && !isUploading ? (_jsxs("div", { className: "flex gap-3", "data-section": "avatarupload-div-410", children: [_jsx(Button, { type: "button", onClick: () => fileInputRef.current?.click(), size: "sm", children: previewUrl ? t.changePhoto : t.chooseImage }), previewUrl ? (_jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: handleRemovePhoto, children: t.removePhoto })) : null] })) : null, _jsx(Input, { ref: fileInputRef, bare: true, type: "file", accept: "image/*", onChange: handleFileSelect, className: "hidden", "aria-label": t.changePhoto })] })] }), uploadApiError ? (_jsx(Alert, { variant: "error", children: uploadApiError.message })) : null] }), showCropModal && tempImageUrl ? (_jsx(ImageCropModal, { isOpen: showCropModal, imageUrl: tempImageUrl, onClose: handleCropCancel, onSave: handleCropSave, initialCropData: cropData || undefined })) : null] }));
109
+ return (_jsxs(_Fragment, { children: [_jsxs(Div, { className: "space-y-4", children: [_jsxs(Div, { className: "flex items-start gap-6", children: [_jsx(Div, { className: "shrink-0", children: _jsx(AvatarDisplay, { cropData: hasPending ? pendingCropData : cropData, size: "2xl", className: `border-4 ${hasPending ? "border-primary/60 ring-2 ring-primary/20" : "border-zinc-200 dark:border-slate-700"}`, displayName: displayName }) }), _jsxs(Div, { className: "flex-1 space-y-3", children: [_jsx(Text, { variant: "secondary", className: "text-xs", children: "JPG, PNG, WEBP or GIF up to 10MB." }), isUploading ? (_jsx(Progress, { value: 50, variant: "primary", size: "sm", label: t.uploading })) : null, hasPending && !isUploading ? (_jsxs(Div, { className: "space-y-2", children: [_jsx(Text, { variant: "secondary", className: "text-xs text-primary", children: t.readyToSave }), _jsxs(Div, { className: "flex gap-3", children: [_jsx(Button, { type: "button", onClick: handleConfirmSave, size: "sm", children: t.saveAvatar }), _jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: handleCancelPending, children: t.cancelChange })] })] })) : null, !hasPending && !isUploading ? (_jsxs(Div, { className: "flex gap-3", children: [_jsx(Button, { type: "button", onClick: () => fileInputRef.current?.click(), size: "sm", children: previewUrl ? t.changePhoto : t.chooseImage }), previewUrl ? (_jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: handleRemovePhoto, children: t.removePhoto })) : null] })) : null, _jsx(Input, { ref: fileInputRef, bare: true, type: "file", accept: "image/*", onChange: handleFileSelect, className: "hidden", "aria-label": t.changePhoto })] })] }), uploadApiError ? (_jsx(Alert, { variant: "error", children: uploadApiError.message })) : null] }), showCropModal && tempImageUrl ? (_jsx(ImageCropModal, { isOpen: showCropModal, imageUrl: tempImageUrl, onClose: handleCropCancel, onSave: handleCropSave, initialCropData: cropData || undefined })) : null] }));
110
110
  }
111
111
  export default AvatarUpload;
@@ -4,6 +4,7 @@ import { useEffect, useCallback, useRef, useState } from "react";
4
4
  import { X, ZoomIn, ZoomOut, Maximize, Minimize, ChevronLeft, ChevronRight, RotateCcw, } from "lucide-react";
5
5
  import { MediaImage } from "./MediaImage";
6
6
  import { Button, Div, Span } from "../../ui";
7
+ const CLS_CLOSE_HOVER = "hover:!bg-red-500/50";
7
8
  const MIN_ZOOM = 1;
8
9
  const MAX_ZOOM = 4;
9
10
  const ZOOM_STEP = 0.5;
@@ -27,7 +28,7 @@ function IconBtn({ onClick, disabled, ariaLabel, ariaCurrent, className, childre
27
28
  }
28
29
  // --- Controls bar sub-components ---------------------------------------------
29
30
  function LightboxControlsBar({ items, index, zoom, isFullscreen, L, goPrev, goNext, zoomIn, zoomOut, resetZoom, toggleFullscreen, onClose, }) {
30
- return (_jsxs(Div, { className: "flex items-center justify-center gap-1.5 px-4 py-3 bg-black/85 backdrop-blur-sm shrink-0 border-t border-white/10 flex-wrap", children: [items.length > 1 && (_jsx(IconBtn, { onClick: (e) => { e.stopPropagation(); goPrev(); }, ariaLabel: L.prevImage, children: _jsx(ChevronLeft, { className: "w-7 h-7" }) })), _jsx(IconBtn, { onClick: zoomOut, disabled: zoom <= MIN_ZOOM, ariaLabel: L.zoomOut, children: _jsx(ZoomOut, { className: "w-7 h-7" }) }), _jsxs(Span, { className: "text-white/70 w-14 text-center tabular-nums text-xs", children: [Math.round(zoom * 100), "%"] }), _jsx(IconBtn, { onClick: zoomIn, disabled: zoom >= MAX_ZOOM, ariaLabel: L.zoomIn, children: _jsx(ZoomIn, { className: "w-7 h-7" }) }), zoom > 1 && (_jsx(IconBtn, { onClick: resetZoom, ariaLabel: L.resetZoom, children: _jsx(RotateCcw, { className: "w-7 h-7" }) })), _jsx(Span, { className: "w-px h-6 bg-white/15 mx-1 shrink-0", "aria-hidden": "true" }), _jsxs(Span, { className: "text-white/60 w-12 text-center tabular-nums text-xs", children: [index + 1, " / ", items.length] }), _jsx(Span, { className: "w-px h-6 bg-white/15 mx-1 shrink-0", "aria-hidden": "true" }), _jsx(IconBtn, { onClick: toggleFullscreen, ariaLabel: isFullscreen ? L.exitFullscreen : L.enterFullscreen, children: isFullscreen ? _jsx(Minimize, { className: "w-6 h-6" }) : _jsx(Maximize, { className: "w-6 h-6" }) }), _jsx(IconBtn, { onClick: onClose, ariaLabel: L.close, className: "hover:!bg-red-500/50", children: _jsx(X, { className: "w-7 h-7" }) }), items.length > 1 && (_jsx(IconBtn, { onClick: (e) => { e.stopPropagation(); goNext(); }, ariaLabel: L.nextImage, children: _jsx(ChevronRight, { className: "w-7 h-7" }) }))] }));
31
+ return (_jsxs(Div, { className: "flex items-center justify-center gap-1.5 px-4 py-3 bg-black/85 backdrop-blur-sm shrink-0 border-t border-white/10 flex-wrap", children: [items.length > 1 && (_jsx(IconBtn, { onClick: (e) => { e.stopPropagation(); goPrev(); }, ariaLabel: L.prevImage, children: _jsx(ChevronLeft, { className: "w-7 h-7" }) })), _jsx(IconBtn, { onClick: zoomOut, disabled: zoom <= MIN_ZOOM, ariaLabel: L.zoomOut, children: _jsx(ZoomOut, { className: "w-7 h-7" }) }), _jsxs(Span, { size: "xs", className: "text-white/70 w-14 text-center tabular-nums", children: [Math.round(zoom * 100), "%"] }), _jsx(IconBtn, { onClick: zoomIn, disabled: zoom >= MAX_ZOOM, ariaLabel: L.zoomIn, children: _jsx(ZoomIn, { className: "w-7 h-7" }) }), zoom > 1 && (_jsx(IconBtn, { onClick: resetZoom, ariaLabel: L.resetZoom, children: _jsx(RotateCcw, { className: "w-7 h-7" }) })), _jsx(Span, { className: "w-px h-6 bg-white/15 mx-1 shrink-0", "aria-hidden": "true" }), _jsxs(Span, { size: "xs", className: "text-white/60 w-12 text-center tabular-nums", children: [index + 1, " / ", items.length] }), _jsx(Span, { className: "w-px h-6 bg-white/15 mx-1 shrink-0", "aria-hidden": "true" }), _jsx(IconBtn, { onClick: toggleFullscreen, ariaLabel: isFullscreen ? L.exitFullscreen : L.enterFullscreen, children: isFullscreen ? _jsx(Minimize, { className: "w-6 h-6" }) : _jsx(Maximize, { className: "w-6 h-6" }) }), _jsx(IconBtn, { onClick: onClose, ariaLabel: L.close, className: CLS_CLOSE_HOVER, children: _jsx(X, { className: "w-7 h-7" }) }), items.length > 1 && (_jsx(IconBtn, { onClick: (e) => { e.stopPropagation(); goNext(); }, ariaLabel: L.nextImage, children: _jsx(ChevronRight, { className: "w-7 h-7" }) }))] }));
31
32
  }
32
33
  function LightboxThumbnailStrip({ items, index, onSelect, resetZoom, L, }) {
33
34
  return (_jsx(Div, { className: "flex gap-2 px-4 py-3 bg-black/70 backdrop-blur-sm overflow-x-auto shrink-0 justify-center", style: { paddingBottom: "calc(0.75rem + env(safe-area-inset-bottom, 0px))" }, children: items.map((item, i) => (_jsx(Button, { type: "button", onClick: () => { onSelect(i); resetZoom(); }, "aria-label": L.imageThumbnail(i + 1), "aria-current": i === index ? "true" : undefined, className: cn("relative shrink-0 w-14 h-14 p-0 overflow-hidden rounded-lg border-2 transition-all active:scale-95", i === index ? "border-white opacity-100" : "border-transparent opacity-40 hover:opacity-75"), children: _jsx(MediaImage, { src: item.src, alt: item.alt, size: "thumbnail" }) }, i))) }));
@@ -222,7 +223,7 @@ export function MediaLightbox({ items, initialIndex = 0, isOpen, onClose, labels
222
223
  if (!isOpen || items.length === 0)
223
224
  return null;
224
225
  const current = items[index];
225
- return (_jsxs(Div, { ref: containerRef, className: "fixed inset-0 z-[9999] bg-black/95 flex flex-col", role: "dialog", "aria-modal": "true", "aria-label": L.lightboxTitle, children: [_jsx(Div, { ref: imageAreaRef, className: "flex-1 relative overflow-hidden select-none", onMouseDown: handleMouseDown, onMouseMove: handleMouseMove, onMouseUp: handleMouseUp, onMouseLeave: handleMouseUp, onTouchStart: handleTouchStart, onTouchMove: handleTouchMove, onTouchEnd: handleTouchEnd, style: {
226
+ return (_jsxs(Div, { ref: containerRef, className: "fixed inset-0 z-[var(--appkit-z-tooltip)] bg-black/95 flex flex-col", role: "dialog", "aria-modal": "true", "aria-label": L.lightboxTitle, children: [_jsx(Div, { ref: imageAreaRef, className: "flex-1 relative overflow-hidden select-none", onMouseDown: handleMouseDown, onMouseMove: handleMouseMove, onMouseUp: handleMouseUp, onMouseLeave: handleMouseUp, onTouchStart: handleTouchStart, onTouchMove: handleTouchMove, onTouchEnd: handleTouchEnd, style: {
226
227
  cursor: zoom > 1 ? (isDragging ? "grabbing" : "grab") : "default",
227
228
  touchAction: "none",
228
229
  }, onClick: (e) => {
@@ -9,6 +9,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
9
  import { useState, useRef } from "react";
10
10
  import { useTranslations } from "next-intl";
11
11
  import { Alert, Button, Div, Modal, Row, Span, Spinner, Text, } from "../../../ui";
12
+ const __O = {
13
+ hidden: "overflow-hidden",
14
+ };
12
15
  export function VideoThumbnailSelector({ isOpen, videoUrl, onClose, onSelect, onUpload, }) {
13
16
  const t = useTranslations("mediaEditor");
14
17
  const [isCapturing, setIsCapturing] = useState(false);
@@ -47,5 +50,5 @@ export function VideoThumbnailSelector({ isOpen, videoUrl, onClose, onSelect, on
47
50
  setIsCapturing(false);
48
51
  }
49
52
  };
50
- return (_jsx(Modal, { isOpen: isOpen, onClose: onClose, title: t("thumbnailTitle"), size: "lg", children: _jsxs(Div, { className: "space-y-4", children: [_jsx(Text, { variant: "secondary", className: "text-xs", children: t("thumbnailInstruction") }), _jsx(Div, { className: "relative aspect-video overflow-hidden rounded-lg bg-black", children: _jsx("video", { ref: videoRef, src: videoUrl, className: "absolute inset-0 w-full h-full object-contain", controls: true, preload: "metadata" }) }), _jsx("canvas", { ref: canvasRef, className: "hidden", "aria-hidden": "true" }), error && _jsx(Alert, { variant: "error", children: error }), _jsxs(Row, { justify: "end", className: "gap-2", children: [_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: onClose, disabled: isCapturing, children: t("thumbnailSkip") }), _jsx(Button, { type: "button", variant: "primary", size: "sm", onClick: handleCapture, disabled: isCapturing, children: isCapturing ? (_jsxs(Span, { className: "flex items-center gap-2", children: [_jsx(Spinner, { size: "sm" }), t("thumbnailCapturing")] })) : (t("thumbnailCapture")) })] })] }) }));
53
+ return (_jsx(Modal, { isOpen: isOpen, onClose: onClose, title: t("thumbnailTitle"), size: "lg", children: _jsxs(Div, { className: "space-y-4", children: [_jsx(Text, { variant: "secondary", className: "text-xs", children: t("thumbnailInstruction") }), _jsx(Div, { className: `relative aspect-video ${__O.hidden} rounded-lg bg-black`, children: _jsx("video", { ref: videoRef, src: videoUrl, className: "absolute inset-0 w-full h-full object-contain", controls: true, preload: "metadata" }) }), _jsx("canvas", { ref: canvasRef, className: "hidden", "aria-hidden": "true" }), error && _jsx(Alert, { variant: "error", children: error }), _jsxs(Row, { justify: "end", className: "gap-2", children: [_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: onClose, disabled: isCapturing, children: t("thumbnailSkip") }), _jsx(Button, { type: "button", variant: "primary", size: "sm", onClick: handleCapture, disabled: isCapturing, children: isCapturing ? (_jsxs(Span, { className: "flex items-center gap-2", children: [_jsx(Spinner, { size: "sm" }), t("thumbnailCapturing")] })) : (t("thumbnailCapture")) })] })] }) }));
51
54
  }
@@ -69,5 +69,5 @@ export function VideoTrimModal({ isOpen, videoUrl, onClose, onSave, endpoint, })
69
69
  medium: t("trimQualityMedium"),
70
70
  high: t("trimQualityHigh"),
71
71
  };
72
- return (_jsx(Modal, { isOpen: isOpen, onClose: onClose, title: t("trimTitle"), size: "lg", children: _jsxs(Stack, { gap: "md", children: [_jsx(Text, { variant: "secondary", className: "text-xs", children: t("trimInstruction") }), _jsx(Div, { className: "relative aspect-video overflow-hidden rounded-lg bg-black", children: _jsx("video", { ref: videoRef, src: videoUrl, className: "absolute inset-0 w-full h-full object-contain", controls: true, onLoadedMetadata: handleLoadedMetadata }) }), duration > 0 && (_jsxs(_Fragment, { children: [_jsxs(Stack, { gap: "xs", children: [_jsxs(Row, { justify: "between", children: [_jsx(Text, { size: "sm", children: t("trimStart") }), _jsx(Span, { className: "text-sm font-mono tabular-nums", children: formatTime(startTime) })] }), _jsx(MediaSlider, { value: startTime, min: 0, max: duration, step: 0.1, onChange: handleStartChange })] }), _jsxs(Stack, { gap: "xs", children: [_jsxs(Row, { justify: "between", children: [_jsx(Text, { size: "sm", children: t("trimEnd") }), _jsx(Span, { className: "text-sm font-mono tabular-nums", children: formatTime(endTime) })] }), _jsx(MediaSlider, { value: endTime, min: 0, max: duration, step: 0.1, onChange: handleEndChange })] }), _jsx(Text, { size: "xs", variant: "secondary", children: t("trimDuration", { duration: (endTime - startTime).toFixed(1) }) }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", children: t("trimQuality") }), _jsx(Div, { className: "flex gap-2", children: ["low", "medium", "high"].map((q) => (_jsx(Button, { type: "button", variant: quality === q ? "primary" : "outline", size: "sm", onClick: () => setQuality(q), disabled: isPending, children: qualityLabels[q] }, q))) })] })] })), error && _jsx(Alert, { variant: "error", children: error }), _jsxs(Row, { justify: "end", className: "gap-2", children: [_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: onClose, disabled: isPending, children: t("trimSkip") }), _jsx(Button, { type: "button", variant: "primary", size: "sm", onClick: handleTrim, disabled: isPending || duration === 0, children: isPending ? t("trimming") : t("trimSave") })] })] }) }));
72
+ return (_jsx(Modal, { isOpen: isOpen, onClose: onClose, title: t("trimTitle"), size: "lg", children: _jsxs(Stack, { gap: "md", children: [_jsx(Text, { variant: "secondary", className: "text-xs", children: t("trimInstruction") }), _jsx(Div, { className: "relative aspect-video overflow-hidden rounded-lg bg-black", children: _jsx("video", { ref: videoRef, src: videoUrl, className: "absolute inset-0 w-full h-full object-contain", controls: true, onLoadedMetadata: handleLoadedMetadata }) }), duration > 0 && (_jsxs(_Fragment, { children: [_jsxs(Stack, { gap: "xs", children: [_jsxs(Row, { justify: "between", children: [_jsx(Text, { size: "sm", children: t("trimStart") }), _jsx(Span, { size: "sm", className: "font-mono tabular-nums", children: formatTime(startTime) })] }), _jsx(MediaSlider, { value: startTime, min: 0, max: duration, step: 0.1, onChange: handleStartChange })] }), _jsxs(Stack, { gap: "xs", children: [_jsxs(Row, { justify: "between", children: [_jsx(Text, { size: "sm", children: t("trimEnd") }), _jsx(Span, { size: "sm", className: "font-mono tabular-nums", children: formatTime(endTime) })] }), _jsx(MediaSlider, { value: endTime, min: 0, max: duration, step: 0.1, onChange: handleEndChange })] }), _jsx(Text, { size: "xs", variant: "secondary", children: t("trimDuration", { duration: (endTime - startTime).toFixed(1) }) }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", children: t("trimQuality") }), _jsx(Div, { className: "flex gap-2", children: ["low", "medium", "high"].map((q) => (_jsx(Button, { type: "button", variant: quality === q ? "primary" : "outline", size: "sm", onClick: () => setQuality(q), disabled: isPending, children: qualityLabels[q] }, q))) })] })] })), error && _jsx(Alert, { variant: "error", children: error }), _jsxs(Row, { justify: "end", className: "gap-2", children: [_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: onClose, disabled: isPending, children: t("trimSkip") }), _jsx(Button, { type: "button", variant: "primary", size: "sm", onClick: handleTrim, disabled: isPending || duration === 0, children: isPending ? t("trimming") : t("trimSave") })] })] }) }));
73
73
  }
@@ -53,7 +53,7 @@ export default function CameraCapture({ mode, facingMode = "environment", onCapt
53
53
  };
54
54
  const showPhotoButton = mode === "photo" || mode === "both";
55
55
  const showVideoButton = mode === "video" || mode === "both";
56
- return (_jsxs(Div, { className: `relative rounded-xl overflow-hidden bg-black ${className ?? ""}`, children: [_jsx("video", { ref: camera.videoRef, autoPlay: true, muted: true, playsInline: true, className: "w-full aspect-video object-cover" }), isStarting && (_jsx(Div, { className: "absolute inset-0 flex items-center justify-center bg-black/60", children: _jsxs(Div, { className: "flex flex-col items-center gap-2", children: [_jsx(Spinner, {}), _jsx(Span, { className: "text-white text-sm", children: t("starting") })] }) })), camera.error && (_jsx(Div, { className: "absolute top-2 left-2 right-2", children: _jsx(Alert, { variant: "error", children: camera.error }) })), !isStarting && !camera.error && camera.isActive && (_jsxs(Div, { className: "absolute bottom-0 left-0 right-0 p-3 bg-black/40 flex items-center justify-center gap-3", children: [showPhotoButton && (_jsx(Button, { variant: "secondary", onClick: handleTakePhoto, "aria-label": t("takePhoto"), disabled: camera.isCapturing, children: t("takePhoto") })), showVideoButton && (_jsx(Button, { variant: camera.isCapturing ? "danger" : "secondary", onClick: camera.isCapturing
56
+ return (_jsxs(Div, { className: `relative rounded-xl overflow-hidden bg-black ${className ?? ""}`, children: [_jsx("video", { ref: camera.videoRef, autoPlay: true, muted: true, playsInline: true, className: "w-full aspect-video object-cover" }), isStarting && (_jsx(Div, { className: "absolute inset-0 flex items-center justify-center bg-black/60", children: _jsxs(Div, { className: "flex flex-col items-center gap-2", children: [_jsx(Spinner, {}), _jsx(Span, { size: "sm", className: "text-white", children: t("starting") })] }) })), camera.error && (_jsx(Div, { className: "absolute top-2 left-2 right-2", children: _jsx(Alert, { variant: "error", children: camera.error }) })), !isStarting && !camera.error && camera.isActive && (_jsxs(Div, { className: "absolute bottom-0 left-0 right-0 p-3 bg-black/40 flex items-center justify-center gap-3", children: [showPhotoButton && (_jsx(Button, { variant: "secondary", onClick: handleTakePhoto, "aria-label": t("takePhoto"), disabled: camera.isCapturing, children: t("takePhoto") })), showVideoButton && (_jsx(Button, { variant: camera.isCapturing ? "danger" : "secondary", onClick: camera.isCapturing
57
57
  ? handleStopRecording
58
58
  : () => camera.startRecording(), "aria-label": camera.isCapturing ? t("stopRecording") : t("startRecording"), children: camera.isCapturing ? t("stopRecording") : t("startRecording") })), hasMultipleCameras && (_jsx(Button, { variant: "outline", onClick: () => void camera.switchCamera(), "aria-label": t("flipCamera"), disabled: camera.isCapturing, children: t("flipCamera") }))] }))] }));
59
59
  }
@@ -15,6 +15,9 @@ import { MediaImage } from "../MediaImage";
15
15
  import { ImageCropModal } from "../modals/ImageCropModal";
16
16
  import { ImageEditor } from "../modals/ImageEditor";
17
17
  import CameraCapture from "./CameraCapture";
18
+ const __O = {
19
+ hidden: "overflow-hidden",
20
+ };
18
21
  function formatFileSize(bytes) {
19
22
  if (bytes < 1024 * 1024)
20
23
  return `${(bytes / 1024).toFixed(1)}KB`;
@@ -162,7 +165,7 @@ export function ImageUpload({ currentImage, onUpload, onChange, accept = "image/
162
165
  fileInputRef.current.value = "";
163
166
  onChange?.("");
164
167
  };
165
- return (_jsxs(Div, { className: "space-y-3", children: [label && (_jsx(Label, { className: "block text-sm font-medium text-zinc-600 dark:text-zinc-400", children: label })), _jsx(Div, { className: "relative", children: preview ? (_jsxs(Div, { className: "space-y-2", children: [_jsxs(Div, { className: "relative h-32 max-w-xs mx-auto overflow-hidden rounded-lg border border-zinc-200 dark:border-zinc-700", children: [_jsx(MediaImage, { src: preview, alt: "Preview", size: "card" }), uploading && progress > 0 && (_jsx(Div, { className: "absolute inset-x-0 bottom-0", children: _jsx(Progress, { value: progress, size: "sm" }) }))] }), !uploading && (_jsxs(Row, { wrap: true, gap: "sm", children: [(enableCrop || enableAdvancedCrop) && (_jsx(Button, { type: "button", onClick: () => openEditor(preview), variant: "secondary", size: "sm", children: tMediaEditor("editImage") })), _jsx(Button, { type: "button", onClick: () => fileInputRef.current?.click(), variant: "outline", size: "sm", children: tUpload("change") }), _jsx(Button, { type: "button", onClick: handleRemove, variant: "danger", size: "sm", children: tUpload("remove") })] }))] })) : (_jsxs(_Fragment, { children: [showCamera && isCameraSupported && (_jsx(CameraCapture, { mode: "photo", facingMode: "environment", onCapture: handleCameraCapture, onError: setError })), !showCamera && (_jsxs(Div, { className: "space-y-2", children: [_jsxs(Row, { gap: "sm", className: "flex-wrap", children: [showFileInput && (_jsx(Button, { type: "button", onClick: () => fileInputRef.current?.click(), disabled: uploading, variant: "outline", size: "sm", children: uploading ? tUpload("uploading") : tUpload("clickToUpload") })), captureSource !== "file-only" && isCameraSupported && (_jsx(Button, { type: "button", onClick: () => setCaptureMode("camera"), disabled: uploading, variant: "ghost", size: "sm", children: t("switchToCamera") })), captureSource !== "file-only" && !isCameraSupported && (_jsx(Button, { type: "button", onClick: () => mobileCaptureRef.current?.click(), disabled: uploading, variant: "ghost", size: "sm", children: t("switchToCamera") }))] }), _jsxs(Text, { size: "xs", variant: "secondary", children: [accept === "image/*"
168
+ return (_jsxs(Div, { className: "space-y-3", children: [label && (_jsx(Label, { className: "block text-sm font-medium text-zinc-600 dark:text-zinc-400", children: label })), _jsx(Div, { className: "relative", children: preview ? (_jsxs(Div, { className: "space-y-2", children: [_jsxs(Div, { className: `relative h-32 max-w-xs mx-auto ${__O.hidden} rounded-lg border border-zinc-200 dark:border-zinc-700`, children: [_jsx(MediaImage, { src: preview, alt: "Preview", size: "card" }), uploading && progress > 0 && (_jsx(Div, { className: "absolute inset-x-0 bottom-0", children: _jsx(Progress, { value: progress, size: "sm" }) }))] }), !uploading && (_jsxs(Row, { wrap: true, gap: "sm", children: [(enableCrop || enableAdvancedCrop) && (_jsx(Button, { type: "button", onClick: () => openEditor(preview), variant: "secondary", size: "sm", children: tMediaEditor("editImage") })), _jsx(Button, { type: "button", onClick: () => fileInputRef.current?.click(), variant: "outline", size: "sm", children: tUpload("change") }), _jsx(Button, { type: "button", onClick: handleRemove, variant: "danger", size: "sm", children: tUpload("remove") })] }))] })) : (_jsxs(_Fragment, { children: [showCamera && isCameraSupported && (_jsx(CameraCapture, { mode: "photo", facingMode: "environment", onCapture: handleCameraCapture, onError: setError })), !showCamera && (_jsxs(Div, { className: "space-y-2", children: [_jsxs(Row, { gap: "sm", className: "flex-wrap", children: [showFileInput && (_jsx(Button, { type: "button", onClick: () => fileInputRef.current?.click(), disabled: uploading, variant: "outline", size: "sm", children: uploading ? tUpload("uploading") : tUpload("clickToUpload") })), captureSource !== "file-only" && isCameraSupported && (_jsx(Button, { type: "button", onClick: () => setCaptureMode("camera"), disabled: uploading, variant: "ghost", size: "sm", children: t("switchToCamera") })), captureSource !== "file-only" && !isCameraSupported && (_jsx(Button, { type: "button", onClick: () => mobileCaptureRef.current?.click(), disabled: uploading, variant: "ghost", size: "sm", children: t("switchToCamera") }))] }), _jsxs(Text, { size: "xs", variant: "secondary", children: [accept === "image/*"
166
169
  ? `JPG PNG GIF WebP`
167
170
  : accept.split(",").map((a) => a.split("/")[1]?.toUpperCase() ?? a).join(" "), " ", "\u2014 max ", maxSizeMB, "MB"] })] }))] })) }), _jsx("input", { ref: fileInputRef, type: "file", accept: accept, onChange: handleFileChange, className: "hidden", "aria-hidden": "true", "data-testid": "media-upload-input" }), showCamera && !isCameraSupported && (_jsx("input", { ref: mobileCaptureRef, type: "file", accept: "image/*", capture: "environment", onChange: handleFileChange, className: "hidden", "aria-hidden": "true", "data-testid": "media-upload-capture-input" })), helperText && !error && (_jsx(Text, { variant: "secondary", size: "xs", children: helperText })), error && _jsx(Alert, { variant: "error", children: error }), uploading && (_jsxs(Row, { className: "gap-2", children: [_jsx(Spinner, { size: "sm" }), _jsx(Text, { size: "sm", variant: "secondary", children: tUpload("uploadingProgress", { progress }) })] })), cropPreviewUrl && !enableAdvancedCrop && (_jsx(ImageCropModal, { isOpen: showCropModal, imageUrl: cropPreviewUrl, onClose: handleCropClose, onSave: handleCropSave })), cropPreviewUrl && enableAdvancedCrop && (_jsx(ImageEditor, { isOpen: showAdvancedEditor, imageUrl: cropPreviewUrl, onClose: handleAdvancedEditorClose, onSave: handleAdvancedEditorSave, aspectRatio: cropAspectRatio }))] }));
168
171
  }