@mohasinac/appkit 2.8.2 → 2.8.3

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 (430) 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 +1 -1
  14. package/dist/client.js +1 -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/core/hooks/useSiteSettings.d.ts +1 -1
  19. package/dist/features/about/components/AboutView.js +5 -2
  20. package/dist/features/about/components/FAQPageView.js +3 -3
  21. package/dist/features/about/components/FeesView.js +13 -5
  22. package/dist/features/about/components/HelpPageView.js +9 -5
  23. package/dist/features/about/components/HowAuctionsWorkView.js +9 -5
  24. package/dist/features/about/components/HowCheckoutWorksView.js +9 -5
  25. package/dist/features/about/components/HowOffersWorkView.js +10 -5
  26. package/dist/features/about/components/HowOrdersWorkView.js +10 -5
  27. package/dist/features/about/components/HowPayoutsWorkView.js +9 -5
  28. package/dist/features/about/components/HowPreOrdersWorkView.js +9 -5
  29. package/dist/features/about/components/HowReviewsWorkView.js +9 -5
  30. package/dist/features/about/components/PolicyPageView.js +3 -3
  31. package/dist/features/about/components/PublicProfileView.js +11 -4
  32. package/dist/features/about/components/SecurityPrivacyView.js +8 -4
  33. package/dist/features/about/components/ShippingPolicyView.js +3 -2
  34. package/dist/features/about/components/TrackOrderView.js +2 -2
  35. package/dist/features/about/components/UnauthorizedView.js +3 -3
  36. package/dist/features/account/components/AddressBook.js +1 -1
  37. package/dist/features/account/components/AddressForm.js +2 -2
  38. package/dist/features/account/components/AddressInlineSelect.d.ts +24 -0
  39. package/dist/features/account/components/AddressInlineSelect.js +78 -0
  40. package/dist/features/account/components/AddressSelectorCreate.d.ts +2 -1
  41. package/dist/features/account/components/AddressSelectorCreate.js +5 -32
  42. package/dist/features/account/components/AddressesIndexListing.js +3 -3
  43. package/dist/features/account/components/ChatWindow.js +2 -1
  44. package/dist/features/account/components/NotificationBell.js +13 -7
  45. package/dist/features/account/components/NotificationPreferencesPanel.js +4 -1
  46. package/dist/features/account/components/UserOffersPanel.js +2 -1
  47. package/dist/features/account/components/UserSidebar.js +11 -7
  48. package/dist/features/account/components/UserSupportView.js +13 -4
  49. package/dist/features/account/components/index.d.ts +2 -0
  50. package/dist/features/account/components/index.js +1 -0
  51. package/dist/features/account/hooks/useAccount.d.ts +2 -2
  52. package/dist/features/account/hooks/useAddressSelector.d.ts +1 -1
  53. package/dist/features/account/hooks/useAddresses.d.ts +2 -2
  54. package/dist/features/account/hooks/useNotifications.d.ts +1 -1
  55. package/dist/features/account/hooks/useProfile.d.ts +1 -1
  56. package/dist/features/account/hooks/usePublicProfile.d.ts +2 -2
  57. package/dist/features/addresses/repository/addresses.repository.d.ts +1 -0
  58. package/dist/features/addresses/repository/addresses.repository.js +13 -0
  59. package/dist/features/admin/components/AdminAdEditorView.js +8 -5
  60. package/dist/features/admin/components/AdminAddressEditorView.js +5 -5
  61. package/dist/features/admin/components/AdminAdsView.js +10 -7
  62. package/dist/features/admin/components/AdminBlogEditorView.js +15 -9
  63. package/dist/features/admin/components/AdminBrandEditorView.js +10 -4
  64. package/dist/features/admin/components/AdminBrandsView.js +4 -4
  65. package/dist/features/admin/components/AdminBundleEditorView.js +4 -5
  66. package/dist/features/admin/components/AdminBundlesView.js +3 -3
  67. package/dist/features/admin/components/AdminCarouselEditorView.js +6 -3
  68. package/dist/features/admin/components/AdminCarouselView.js +6 -6
  69. package/dist/features/admin/components/AdminCatalogGuideView.js +2 -1
  70. package/dist/features/admin/components/AdminCategoriesView.js +5 -5
  71. package/dist/features/admin/components/AdminCategoryEditorView.js +11 -5
  72. package/dist/features/admin/components/AdminContactEditorView.js +8 -1
  73. package/dist/features/admin/components/AdminCouponEditorView.js +23 -5
  74. package/dist/features/admin/components/AdminEmployeeEditorView.js +7 -4
  75. package/dist/features/admin/components/AdminFaqEditorView.js +9 -3
  76. package/dist/features/admin/components/AdminFaqsView.js +4 -4
  77. package/dist/features/admin/components/AdminFeatureEditorView.js +7 -1
  78. package/dist/features/admin/components/AdminFeatureFlagsView.js +4 -1
  79. package/dist/features/admin/components/AdminFilterBar.js +4 -4
  80. package/dist/features/admin/components/AdminGroupedListingsView.js +65 -30
  81. package/dist/features/admin/components/AdminGuideHubView.js +4 -1
  82. package/dist/features/admin/components/AdminMediaView.js +4 -1
  83. package/dist/features/admin/components/AdminNavigationView.js +7 -4
  84. package/dist/features/admin/components/AdminNotificationsView.js +2 -2
  85. package/dist/features/admin/components/AdminOrderEditorView.js +2 -2
  86. package/dist/features/admin/components/AdminPageHeader.js +5 -2
  87. package/dist/features/admin/components/AdminPrizeDrawsView.js +5 -5
  88. package/dist/features/admin/components/AdminProductEditorView.js +12 -5
  89. package/dist/features/admin/components/AdminProductsView.js +4 -4
  90. package/dist/features/admin/components/AdminReviewsView.js +2 -2
  91. package/dist/features/admin/components/AdminScammerEditorView.js +6 -2
  92. package/dist/features/admin/components/AdminScammersView.js +3 -3
  93. package/dist/features/admin/components/AdminSectionsView.js +20 -22
  94. package/dist/features/admin/components/AdminSessionsManager.js +2 -1
  95. package/dist/features/admin/components/AdminSessionsView.js +2 -2
  96. package/dist/features/admin/components/AdminSidebar.js +11 -7
  97. package/dist/features/admin/components/AdminSiteConfigGuideView.js +2 -1
  98. package/dist/features/admin/components/AdminSiteSettingsView.js +5 -1
  99. package/dist/features/admin/components/AdminStoreAddressesView.js +2 -2
  100. package/dist/features/admin/components/AdminStoreEditorView.js +5 -5
  101. package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +3 -3
  102. package/dist/features/admin/components/AdminSupportTicketDetailView.js +10 -3
  103. package/dist/features/admin/components/AdminSupportTicketsView.js +3 -3
  104. package/dist/features/admin/components/AdminTrustGuideView.js +3 -3
  105. package/dist/features/admin/components/AdminUsersGuideView.js +3 -3
  106. package/dist/features/admin/components/AdminViewCards.js +12 -6
  107. package/dist/features/admin/components/BrandQuickCreateForm.js +2 -2
  108. package/dist/features/admin/components/CategoryQuickCreateForm.js +2 -2
  109. package/dist/features/admin/components/DashboardStats.js +9 -3
  110. package/dist/features/admin/components/DataListingView.js +3 -3
  111. package/dist/features/admin/components/DataTable.js +11 -7
  112. package/dist/features/admin/components/DrawerFormFooter.js +2 -2
  113. package/dist/features/admin/components/QuickEditMenu.js +2 -1
  114. package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +5 -1
  115. package/dist/features/admin/hooks/useAdmin.d.ts +1 -1
  116. package/dist/features/admin/hooks/useAdminSectionsListing.d.ts +1 -1
  117. package/dist/features/admin/hooks/useChat.d.ts +1 -1
  118. package/dist/features/auctions/components/AuctionBidsTable.js +4 -1
  119. package/dist/features/auctions/components/AuctionDetailPageView.js +14 -6
  120. package/dist/features/auctions/components/CollapsibleBidHistory.js +5 -1
  121. package/dist/features/auctions/components/MarketplaceAuctionCard.js +9 -3
  122. package/dist/features/auctions/components/MarketplaceAuctionGrid.js +8 -2
  123. package/dist/features/auctions/components/PlaceBidFormClient.js +4 -1
  124. package/dist/features/auctions/hooks/useAuctions.d.ts +8 -8
  125. package/dist/features/auth/components/RegisterForm.js +2 -2
  126. package/dist/features/auth/components/VerifyEmailView.js +5 -2
  127. package/dist/features/auth/hooks/useAuth.d.ts +2 -2
  128. package/dist/features/before-after/components/BeforeAfterSlider.js +1 -1
  129. package/dist/features/blog/components/BlogFeaturedCard.js +8 -1
  130. package/dist/features/blog/components/BlogIndexListing.js +11 -5
  131. package/dist/features/blog/components/BlogListView.js +11 -3
  132. package/dist/features/blog/components/BlogPostView.js +10 -3
  133. package/dist/features/cart/components/CartDrawer.js +11 -3
  134. package/dist/features/cart/components/CartSummary.js +2 -2
  135. package/dist/features/cart/components/CheckoutOtpModal.js +2 -1
  136. package/dist/features/cart/hooks/useCart.d.ts +1 -1
  137. package/dist/features/cart/hooks/useCartQuery.d.ts +1 -1
  138. package/dist/features/cart/hooks/useCheckoutReadQueries.d.ts +2 -2
  139. package/dist/features/cart/hooks/useOrder.d.ts +2 -2
  140. package/dist/features/categories/components/BrandDetailPageView.js +5 -2
  141. package/dist/features/categories/components/BrandDetailTabs.js +5 -1
  142. package/dist/features/categories/components/BundleDetailView.js +6 -3
  143. package/dist/features/categories/components/BundleDynamicRuleEditor.js +3 -1
  144. package/dist/features/categories/components/BundleItemsPicker.js +10 -3
  145. package/dist/features/categories/components/CategoriesIndexListing.js +12 -6
  146. package/dist/features/categories/components/CategoryBundlesListing.js +5 -2
  147. package/dist/features/categories/components/CategoryDetailPageView.js +6 -2
  148. package/dist/features/categories/components/CategoryDetailTabs.js +5 -1
  149. package/dist/features/categories/components/CategoryForm.js +6 -3
  150. package/dist/features/categories/components/CategoryGrid.js +9 -2
  151. package/dist/features/categories/components/CategoryProductsListing.js +10 -4
  152. package/dist/features/categories/components/CategorySelectorCreate.js +3 -3
  153. package/dist/features/categories/components/CategorySortSelect.js +1 -1
  154. package/dist/features/categories/components/CategoryStoresListing.js +3 -3
  155. package/dist/features/categories/components/CategoryTableColumns.js +10 -6
  156. package/dist/features/categories/components/CategoryTree.js +1 -1
  157. package/dist/features/categories/hooks/useCategories.d.ts +3 -3
  158. package/dist/features/categories/hooks/useCategorySelector.d.ts +3 -3
  159. package/dist/features/categories/hooks/useCategoryTree.d.ts +1 -1
  160. package/dist/features/checkout/hooks/useCheckoutApi.d.ts +2 -2
  161. package/dist/features/classified/components/ClassifiedFilters.js +2 -2
  162. package/dist/features/classified/components/ClassifiedIndexListing.js +9 -3
  163. package/dist/features/collections/components/CollectionCard.js +2 -1
  164. package/dist/features/collections/hooks/useCollections.d.ts +2 -2
  165. package/dist/features/contact/components/ContactForm.js +4 -2
  166. package/dist/features/contact/components/ContactInfoSidebar.js +4 -1
  167. package/dist/features/copilot/components/AdminCopilotView.js +13 -5
  168. package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +9 -3
  169. package/dist/features/events/components/AdminEventEditorView.js +62 -40
  170. package/dist/features/events/components/AdminEventEntriesView.js +9 -6
  171. package/dist/features/events/components/EventCard.js +7 -1
  172. package/dist/features/events/components/EventFormDrawer.js +2 -1
  173. package/dist/features/events/components/EventLeaderboard.js +4 -4
  174. package/dist/features/events/components/EventOfferCard.js +4 -1
  175. package/dist/features/events/components/EventParticipateView.js +3 -2
  176. package/dist/features/events/components/EventPollWidget.js +6 -5
  177. package/dist/features/events/components/EventRaffleEntryForm.js +5 -2
  178. package/dist/features/events/components/EventRaffleWinnerView.js +7 -1
  179. package/dist/features/events/components/EventRafflesSection.js +2 -2
  180. package/dist/features/events/components/EventSaleBanner.js +5 -2
  181. package/dist/features/events/components/EventsIndexListing.js +8 -2
  182. package/dist/features/events/components/EventsListView.js +4 -1
  183. package/dist/features/events/components/SpinWheelView.js +7 -2
  184. package/dist/features/events/hooks/useEvent.d.ts +3 -3
  185. package/dist/features/events/hooks/useEvents.d.ts +1 -1
  186. package/dist/features/events/schemas/firestore.d.ts +1 -0
  187. package/dist/features/events/types/index.d.ts +1 -0
  188. package/dist/features/faq/components/ContactCTA.js +4 -1
  189. package/dist/features/faq/components/FAQCategorySidebar.js +2 -2
  190. package/dist/features/faq/components/FAQHelpfulButtons.js +8 -5
  191. package/dist/features/faq/components/FAQPageContent.js +5 -5
  192. package/dist/features/faq/components/FAQSortDropdown.js +2 -2
  193. package/dist/features/faq/hooks/useFAQs.d.ts +1 -1
  194. package/dist/features/faq/hooks/useFaqList.d.ts +15 -15
  195. package/dist/features/filters/AsyncFacetSection.js +4 -2
  196. package/dist/features/filters/FilterFacetSection.js +14 -6
  197. package/dist/features/filters/RangeFilter.js +4 -2
  198. package/dist/features/filters/SwitchFilter.js +2 -1
  199. package/dist/features/forms/Checkbox.js +1 -1
  200. package/dist/features/forms/Radio.js +1 -1
  201. package/dist/features/forms/Slider.js +1 -1
  202. package/dist/features/homepage/components/AdSlot.js +4 -4
  203. package/dist/features/homepage/components/AdvertisementBanner.js +13 -4
  204. package/dist/features/homepage/components/AnnouncementBar.js +2 -1
  205. package/dist/features/homepage/components/BeforeAfterCard.js +8 -2
  206. package/dist/features/homepage/components/BrandsSection.js +6 -3
  207. package/dist/features/homepage/components/CTABannerSection.js +2 -2
  208. package/dist/features/homepage/components/CharacterHotspot.js +5 -2
  209. package/dist/features/homepage/components/CharacterHotspotForm.js +8 -4
  210. package/dist/features/homepage/components/CustomCardsSection.js +13 -7
  211. package/dist/features/homepage/components/CustomerReviewsSection.js +9 -3
  212. package/dist/features/homepage/components/FAQSection.js +7 -4
  213. package/dist/features/homepage/components/FeaturedBundlesSection.js +8 -2
  214. package/dist/features/homepage/components/FeaturedResultsSection.js +1 -1
  215. package/dist/features/homepage/components/GoogleReviewsSection.js +14 -8
  216. package/dist/features/homepage/components/HeroCarousel.js +1 -1
  217. package/dist/features/homepage/components/HomepageSkeleton.js +7 -1
  218. package/dist/features/homepage/components/HowItWorksInfoView.js +2 -2
  219. package/dist/features/homepage/components/HowItWorksSection.js +2 -2
  220. package/dist/features/homepage/components/NewsletterBanner.js +3 -2
  221. package/dist/features/homepage/components/NewsletterSection.js +5 -2
  222. package/dist/features/homepage/components/PromoGrid.js +4 -1
  223. package/dist/features/homepage/components/SectionCarousel.js +7 -4
  224. package/dist/features/homepage/components/SecurityHighlightsSection.js +3 -3
  225. package/dist/features/homepage/components/ShopByCategorySection.js +10 -4
  226. package/dist/features/homepage/components/SiteFeaturesSection.js +5 -2
  227. package/dist/features/homepage/components/SocialFeedSection.js +4 -4
  228. package/dist/features/homepage/components/SocialPostCard.js +6 -3
  229. package/dist/features/homepage/components/TrustFeaturesSection.js +5 -5
  230. package/dist/features/homepage/components/TrustIndicatorsSection.js +5 -2
  231. package/dist/features/homepage/components/WelcomeSection.js +1 -1
  232. package/dist/features/homepage/components/WhatsAppCommunitySection.js +3 -3
  233. package/dist/features/homepage/hooks/useBlogArticles.d.ts +1 -1
  234. package/dist/features/homepage/hooks/useFeaturedAuctions.d.ts +1 -1
  235. package/dist/features/homepage/hooks/useFeaturedPreOrders.d.ts +1 -1
  236. package/dist/features/homepage/hooks/useFeaturedProducts.d.ts +1 -1
  237. package/dist/features/homepage/hooks/useFeaturedStores.d.ts +1 -1
  238. package/dist/features/homepage/hooks/useHeroCarousel.d.ts +1 -1
  239. package/dist/features/homepage/hooks/useHomepageEvents.d.ts +1 -1
  240. package/dist/features/homepage/hooks/useHomepageReviews.d.ts +1 -1
  241. package/dist/features/homepage/hooks/useHomepageSections.d.ts +1 -1
  242. package/dist/features/homepage/hooks/useTopBrands.d.ts +1 -1
  243. package/dist/features/homepage/hooks/useTopCategories.d.ts +1 -1
  244. package/dist/features/layout/AppLayoutShell.js +2 -1
  245. package/dist/features/layout/BackToTop.js +1 -1
  246. package/dist/features/layout/BottomActions.js +4 -3
  247. package/dist/features/layout/BottomNavItem.js +1 -1
  248. package/dist/features/layout/BottomSheet.js +4 -1
  249. package/dist/features/layout/FooterLayout.js +1 -1
  250. package/dist/features/layout/NavbarLayout.js +4 -1
  251. package/dist/features/layout/SidebarLayout.js +5 -2
  252. package/dist/features/live/components/LiveItemFilters.js +2 -2
  253. package/dist/features/live/components/LiveItemsIndexListing.js +9 -3
  254. package/dist/features/loyalty/components/CoinsDisplay.js +4 -2
  255. package/dist/features/loyalty/hooks/useLoyaltyBalance.d.ts +1 -1
  256. package/dist/features/media/AvatarUpload.js +2 -2
  257. package/dist/features/media/MediaLightbox.js +3 -2
  258. package/dist/features/media/modals/VideoThumbnailSelector.js +4 -1
  259. package/dist/features/media/modals/VideoTrimModal.js +1 -1
  260. package/dist/features/media/upload/CameraCapture.js +1 -1
  261. package/dist/features/media/upload/ImageUpload.js +4 -1
  262. package/dist/features/media/upload/MediaUploadField.js +11 -2
  263. package/dist/features/media/upload/MediaUploadList.js +5 -1
  264. package/dist/features/orders/components/MarketplaceOrderCard.js +2 -2
  265. package/dist/features/orders/components/OrdersList.js +2 -1
  266. package/dist/features/orders/components/RefundHistoryTable.js +4 -1
  267. package/dist/features/orders/components/RefundRequestView.js +2 -1
  268. package/dist/features/orders/hooks/useOrders.d.ts +2 -2
  269. package/dist/features/payments/hooks/usePayments.d.ts +1 -1
  270. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +5 -1
  271. package/dist/features/pre-orders/components/PreOrderActionsClient.js +3 -3
  272. package/dist/features/pre-orders/components/PreOrderBadge.js +2 -1
  273. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +16 -7
  274. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +32 -24
  275. package/dist/features/pre-orders/hooks/usePreOrders.d.ts +2 -2
  276. package/dist/features/products/columns/productTableColumns.js +9 -4
  277. package/dist/features/products/components/AuctionsIndexListing.js +9 -3
  278. package/dist/features/products/components/BidHistory.js +4 -4
  279. package/dist/features/products/components/CompareOverlay.js +10 -2
  280. package/dist/features/products/components/CustomFieldsEditor.js +2 -1
  281. package/dist/features/products/components/CustomSectionTabContent.js +2 -2
  282. package/dist/features/products/components/CustomSectionsEditor.js +3 -2
  283. package/dist/features/products/components/GroupSettingsPanel.js +34 -26
  284. package/dist/features/products/components/MakeOfferButton.js +6 -2
  285. package/dist/features/products/components/MakeOfferForm.js +2 -1
  286. package/dist/features/products/components/MarketplaceBundleCard.js +6 -3
  287. package/dist/features/products/components/MarketplacePrizeDrawCard.js +3 -2
  288. package/dist/features/products/components/PlaceBidForm.js +2 -1
  289. package/dist/features/products/components/PrizeDrawCollage.js +6 -2
  290. package/dist/features/products/components/PrizeDrawDetailPageView.js +6 -1
  291. package/dist/features/products/components/PrizeDrawItemsEditor.js +4 -2
  292. package/dist/features/products/components/PrizeDrawsIndexListing.js +6 -3
  293. package/dist/features/products/components/PrizeDrawsSection.js +2 -2
  294. package/dist/features/products/components/PrizeRevealModal.js +5 -1
  295. package/dist/features/products/components/ProductDetailPageView.js +32 -16
  296. package/dist/features/products/components/ProductFeatureBadges.js +9 -9
  297. package/dist/features/products/components/ProductForm.d.ts +11 -1
  298. package/dist/features/products/components/ProductForm.js +10 -5
  299. package/dist/features/products/components/ProductGalleryClient.js +8 -4
  300. package/dist/features/products/components/ProductGradingTab.js +4 -1
  301. package/dist/features/products/components/ProductGrid.js +35 -14
  302. package/dist/features/products/components/ProductInfo.js +2 -1
  303. package/dist/features/products/components/ProductTabs.js +2 -1
  304. package/dist/features/products/components/ProductTabsShell.js +5 -1
  305. package/dist/features/products/components/ProductsIndexListing.js +32 -24
  306. package/dist/features/products/components/ProductsIndexPageView.js +2 -2
  307. package/dist/features/products/components/RelatedProducts.js +3 -3
  308. package/dist/features/products/components/ShowGroupSection.js +10 -6
  309. package/dist/features/products/components/SublistingCarouselSection.js +7 -3
  310. package/dist/features/products/components/SublistingCategorySelect.d.ts +3 -1
  311. package/dist/features/products/components/SublistingCategorySelect.js +4 -37
  312. package/dist/features/products/constants/action-defs.js +3 -3
  313. package/dist/features/products/hooks/useProductDetail.d.ts +1 -1
  314. package/dist/features/products/hooks/useRelatedProducts.d.ts +1 -1
  315. package/dist/features/promotions/components/CouponCard.js +5 -3
  316. package/dist/features/promotions/components/CouponsIndexListing.js +7 -3
  317. package/dist/features/promotions/hooks/usePromotions.d.ts +2 -2
  318. package/dist/features/promotions/repository/coupons.repository.d.ts +8 -0
  319. package/dist/features/promotions/repository/coupons.repository.js +2 -0
  320. package/dist/features/reviews/components/ReviewDetailPageView.js +3 -3
  321. package/dist/features/reviews/components/ReviewDetailShell.js +15 -3
  322. package/dist/features/reviews/components/ReviewSummary.js +4 -2
  323. package/dist/features/reviews/components/ReviewsIndexListing.js +8 -2
  324. package/dist/features/reviews/components/ReviewsList.js +1 -1
  325. package/dist/features/reviews/hooks/useReviews.d.ts +2 -2
  326. package/dist/features/scams/components/ScamAwarenessModal.js +2 -2
  327. package/dist/features/scams/components/ScamProfileView.js +3 -3
  328. package/dist/features/scams/components/ScamRegistryView.js +6 -4
  329. package/dist/features/search/components/Search.js +9 -6
  330. package/dist/features/search/components/SearchFiltersRow.js +1 -1
  331. package/dist/features/search/components/SearchResultsSection.js +1 -1
  332. package/dist/features/search/hooks/useSearch.d.ts +2 -2
  333. package/dist/features/seller/components/CouponInlineSelect.d.ts +22 -0
  334. package/dist/features/seller/components/CouponInlineSelect.js +103 -0
  335. package/dist/features/seller/components/GroupInlineSelect.d.ts +23 -0
  336. package/dist/features/seller/components/GroupInlineSelect.js +80 -0
  337. package/dist/features/seller/components/PhysicalLocationModal.js +2 -1
  338. package/dist/features/seller/components/PrintCenterView.js +2 -1
  339. package/dist/features/seller/components/ProductInlineSelect.d.ts +24 -0
  340. package/dist/features/seller/components/ProductInlineSelect.js +42 -0
  341. package/dist/features/seller/components/QuickProductForm.js +4 -1
  342. package/dist/features/seller/components/SellerAddressesView.js +8 -3
  343. package/dist/features/seller/components/SellerAnalyticsAlertsView.js +6 -3
  344. package/dist/features/seller/components/SellerAnalyticsView.js +2 -2
  345. package/dist/features/seller/components/SellerBidsView.js +7 -7
  346. package/dist/features/seller/components/SellerBundlesView.js +2 -1
  347. package/dist/features/seller/components/SellerCouponEditorView.d.ts +2 -0
  348. package/dist/features/seller/components/SellerCouponEditorView.js +15 -3
  349. package/dist/features/seller/components/SellerCouponsView.js +1 -1
  350. package/dist/features/seller/components/SellerDashboardView.js +2 -2
  351. package/dist/features/seller/components/SellerDigitalCodesView.js +2 -2
  352. package/dist/features/seller/components/SellerGoogleReviewsView.js +2 -2
  353. package/dist/features/seller/components/SellerGroupedListingsView.js +5 -5
  354. package/dist/features/seller/components/SellerOrdersView.js +13 -10
  355. package/dist/features/seller/components/SellerPayoutMethodsView.js +5 -4
  356. package/dist/features/seller/components/SellerPayoutRequestView.js +5 -1
  357. package/dist/features/seller/components/SellerPayoutSettingsView.js +5 -2
  358. package/dist/features/seller/components/SellerPreOrdersView.js +6 -6
  359. package/dist/features/seller/components/SellerPrizeDrawsView.js +6 -6
  360. package/dist/features/seller/components/SellerProductShell.js +1 -1
  361. package/dist/features/seller/components/SellerProductsCards.js +4 -1
  362. package/dist/features/seller/components/SellerProductsView.js +5 -5
  363. package/dist/features/seller/components/SellerReviewsView.js +7 -3
  364. package/dist/features/seller/components/SellerShippingConfigsView.js +4 -4
  365. package/dist/features/seller/components/SellerShippingView.js +1 -1
  366. package/dist/features/seller/components/SellerSidebar.js +15 -8
  367. package/dist/features/seller/components/SellerStoreCategoriesView.js +1 -1
  368. package/dist/features/seller/components/SellerStorefrontView.js +2 -2
  369. package/dist/features/seller/components/SellerTemplatesView.js +7 -4
  370. package/dist/features/seller/components/SublistingInlineSelect.d.ts +19 -0
  371. package/dist/features/seller/components/SublistingInlineSelect.js +83 -0
  372. package/dist/features/seller/components/analytics/SellerTopProducts.js +1 -1
  373. package/dist/features/seller/components/index.d.ts +8 -0
  374. package/dist/features/seller/components/index.js +4 -0
  375. package/dist/features/seller/hooks/useSellerPayouts.d.ts +3 -3
  376. package/dist/features/seller/hooks/useSellerStore.d.ts +6 -6
  377. package/dist/features/seller/hooks/useSellerStorefront.d.ts +2 -2
  378. package/dist/features/shell/FormShell.js +10 -2
  379. package/dist/features/shell/QuickFormDrawer.js +5 -5
  380. package/dist/features/shell/StepForm.js +6 -6
  381. package/dist/features/site-settings/components/ActionPermissionsManager.js +8 -4
  382. package/dist/features/site-settings/components/NavPermissionsManager.js +7 -4
  383. package/dist/features/stores/components/InteractiveStoreCard.js +5 -1
  384. package/dist/features/stores/components/StoreAboutView.js +4 -1
  385. package/dist/features/stores/components/StoreAddressSelectorCreate.d.ts +2 -1
  386. package/dist/features/stores/components/StoreAddressSelectorCreate.js +5 -31
  387. package/dist/features/stores/components/StoreAuctionsListing.js +6 -3
  388. package/dist/features/stores/components/StoreGuideHubView.js +5 -2
  389. package/dist/features/stores/components/StoreHeader.js +8 -1
  390. package/dist/features/stores/components/StorePreOrdersListing.js +6 -3
  391. package/dist/features/stores/components/StoreProductsListing.js +6 -3
  392. package/dist/features/stores/components/StoreReviewsListing.js +8 -2
  393. package/dist/features/stores/components/StoresIndexListing.js +12 -6
  394. package/dist/features/stores/hooks/useStoreAddressSelector.d.ts +1 -1
  395. package/dist/features/stores/hooks/useStores.d.ts +6 -6
  396. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +7 -1
  397. package/dist/features/whatsapp-bot/components/WhatsAppChatButton.js +2 -1
  398. package/dist/features/wishlist/components/WishlistPage.js +2 -1
  399. package/dist/features/wishlist/hooks/useUserWishlist.d.ts +15 -15
  400. package/dist/features/wishlist/hooks/useWishlist.d.ts +1 -1
  401. package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
  402. package/dist/index.d.ts +10 -0
  403. package/dist/index.js +13 -1
  404. package/dist/next/components/GlobalError.js +2 -2
  405. package/dist/next/routing/route-map.d.ts +2 -0
  406. package/dist/next/routing/route-map.js +1 -0
  407. package/dist/react/ErrorBoundary.js +2 -2
  408. package/dist/styles.css +2 -1
  409. package/dist/tailwind-utilities.css +1 -1
  410. package/dist/ui/DataTable.js +17 -16
  411. package/dist/ui/components/DateInput.js +2 -2
  412. package/dist/ui/components/DetailPageGallery.js +4 -1
  413. package/dist/ui/components/DetailPageTabs.js +6 -2
  414. package/dist/ui/components/ImageLightbox.js +5 -3
  415. package/dist/ui/components/Input.js +6 -3
  416. package/dist/ui/components/Layout.d.ts +4 -0
  417. package/dist/ui/components/Layout.js +1 -1
  418. package/dist/ui/components/Layout.style.css +1 -0
  419. package/dist/ui/components/ListingFilterDrawer.js +4 -1
  420. package/dist/ui/components/ListingLayout.js +9 -8
  421. package/dist/ui/components/ListingToolbar.js +5 -1
  422. package/dist/ui/components/PaginatedSelect.d.ts +1 -2
  423. package/dist/ui/components/PaginatedSelect.js +1 -2
  424. package/dist/ui/components/Radio.js +1 -1
  425. package/dist/ui/components/Select.js +2 -1
  426. package/dist/ui/components/Slider.js +1 -1
  427. package/dist/ui/components/VacationBanner.js +2 -1
  428. package/dist/ui/components/surface-tokens.d.ts +1 -0
  429. package/dist/ui/components/surface-tokens.js +1 -0
  430. package/package.json +11 -2
@@ -4,4 +4,4 @@ export interface UseHomepageReviewsOptions {
4
4
  initialData?: Review[];
5
5
  staleTime?: number;
6
6
  }
7
- export declare function useHomepageReviews(options?: UseHomepageReviewsOptions): import("@tanstack/react-query").UseQueryResult<Review[], Error>;
7
+ export declare function useHomepageReviews(options?: UseHomepageReviewsOptions): import("@tanstack/react-query").UseQueryResult<NoInfer<Review[]>, Error>;
@@ -1,2 +1,2 @@
1
1
  import type { HomepageSectionDocument } from "../schemas";
2
- export declare function useHomepageSections(params?: string): import("@tanstack/react-query").UseQueryResult<HomepageSectionDocument[], Error>;
2
+ export declare function useHomepageSections(params?: string): import("@tanstack/react-query").UseQueryResult<NoInfer<HomepageSectionDocument[]>, Error>;
@@ -1,4 +1,4 @@
1
1
  import type { CategoryItem } from "../../categories/types";
2
2
  export declare function useTopBrands(limit?: number, options?: {
3
3
  initialData?: CategoryItem[];
4
- }): import("@tanstack/react-query").UseQueryResult<CategoryItem[], Error>;
4
+ }): import("@tanstack/react-query").UseQueryResult<NoInfer<CategoryItem[]>, Error>;
@@ -1,4 +1,4 @@
1
1
  import type { CategoryItem } from "../../categories/types";
2
2
  export declare function useTopCategories(limit?: number, options?: {
3
3
  initialData?: CategoryItem[];
4
- }): import("@tanstack/react-query").UseQueryResult<CategoryItem[], Error>;
4
+ }): import("@tanstack/react-query").UseQueryResult<NoInfer<CategoryItem[]>, Error>;
@@ -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
  }
@@ -31,12 +31,13 @@ import { useState, useRef, useEffect } from "react";
31
31
  import { X, ChevronUp, ChevronDown, Check } from "lucide-react";
32
32
  import { useBottomActionsContext } from "./BottomActionsContext";
33
33
  import { useClickOutside } from "../../react";
34
- import { Row, Span, Text, Button } from "../../ui";
34
+ import { Div, Row, Span, Text, Button } from "../../ui";
35
35
  // Token values inlined from @mohasinac/appkit/tokens
36
36
  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
37
  const Z_BOTTOM_ACTIONS = "z-40";
38
38
  const BOTTOM_NAV_HEIGHT = "h-14";
39
39
  const FLEX_CENTER = "flex items-center justify-center";
40
+ const CLS_COUNT_BADGE = "bg-red-500 text-white";
40
41
  // ─── Sub-components ───────────────────────────────────────────────────────────
41
42
  function BulkPickerPanel({ bulkActions, selectedActionId, pickerOpen, onSelect, }) {
42
43
  return (_jsx("div", { role: "listbox", "aria-label": "Bulk actions", className: [
@@ -75,7 +76,7 @@ function PageActionsRow({ pageActions, dispatchAction, }) {
75
76
  isIconOnly ? "px-0 justify-center" : "",
76
77
  ]
77
78
  .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));
79
+ .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
80
  }) }));
80
81
  }
81
82
  export default function BottomActions() {
@@ -126,7 +127,7 @@ export default function BottomActions() {
126
127
  isVisible ? "translate-y-0" : "translate-y-full pointer-events-none",
127
128
  ]
128
129
  .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
130
+ .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
131
  ? `${bulk.selectedCount} ${bulk.noun}`
131
132
  : `${bulk.selectedCount} selected` })] }), bulkActions.length > 0 && (_jsxs(Button, { type: "button", variant: "ghost", onClick: () => setPickerOpen((o) => !o), "aria-haspopup": "listbox", "aria-expanded": pickerOpen, className: [
132
133
  "flex-1 min-w-0 h-10 flex items-center gap-2 px-3 rounded-lg border text-sm font-medium transition-colors",
@@ -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,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,4 +1,4 @@
1
1
  import type { LoyaltyBalance } from "../types";
2
2
  export declare function useLoyaltyBalance(uid: string | undefined, opts?: {
3
3
  endpoint?: string;
4
- }): import("@tanstack/react-query").UseQueryResult<LoyaltyBalance | null, Error>;
4
+ }): import("@tanstack/react-query").UseQueryResult<NoInfer<LoyaltyBalance | null>, Error>;
@@ -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
  }
@@ -9,13 +9,22 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
9
9
  import { useState, useRef, useEffect } from "react";
10
10
  import { useTranslations } from "next-intl";
11
11
  import { useCamera } from "../../../react";
12
- import { Alert, Button, Div, Label, Row, Spinner, Text } from "../../../ui";
12
+ import { Alert, Button, Div, Label, Row, Span, Spinner, Text } from "../../../ui";
13
13
  import { MediaImage } from "../MediaImage";
14
14
  import { MediaVideo } from "../MediaVideo";
15
15
  import { VideoTrimModal } from "../modals/VideoTrimModal";
16
16
  import { VideoThumbnailSelector } from "../modals/VideoThumbnailSelector";
17
17
  import CameraCapture from "./CameraCapture";
18
18
  import { inferMediaTypeFromMime } from "../types/index";
19
+ const __P = {
20
+ p3: "p-3",
21
+ };
22
+ const __O = {
23
+ hidden: "overflow-hidden",
24
+ };
25
+ const CLS_PDF_BADGE = "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-rose-100 text-rose-700 dark:bg-rose-900/40 dark:text-rose-300";
26
+ const CLS_PDF_NAME = "text-sm font-medium text-blue-600 underline break-all dark:text-blue-400";
27
+ const CLS_PDF_LINK = "text-sm underline break-all text-blue-600 dark:text-blue-400";
19
28
  const KIND_DEFAULTS = {
20
29
  image: { accept: "image/*", maxSizeMB: 25 },
21
30
  video: { accept: "video/*", maxSizeMB: 200 },
@@ -72,7 +81,7 @@ function ExternalUrlTabPanel({ extInput, setExtInput, extError, setExtError, onA
72
81
  return (_jsxs(Div, { className: "space-y-2", children: [_jsxs(Row, { gap: "sm", children: [_jsx("input", { type: "url", value: extInput, onChange: (e) => { setExtInput(e.target.value); setExtError(""); }, placeholder: "https://example.com/image.jpg", className: "appkit-input flex-1" }), _jsx(Button, { type: "button", variant: "primary", size: "sm", onClick: onApply, children: "Apply" })] }), extError && _jsx(Alert, { variant: "error", children: extError }), _jsx(Text, { size: "xs", variant: "secondary", children: "External URLs are stored as-is and are not watermarked." })] }));
73
82
  }
74
83
  function MediaPreviewPanel({ value, label, disabled, enableTrim, enableThumbnail, onEditVideo, onRemove, tUpload, tMediaEditor, }) {
75
- return (_jsxs(Div, { className: "rounded-lg border border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-900 p-3", children: [isVideo(value) ? (_jsxs(Div, { className: "space-y-2", children: [_jsx(Div, { className: "relative aspect-video overflow-hidden rounded-lg", children: _jsx(MediaVideo, { src: value, alt: label, controls: true, objectFit: "contain" }) }), _jsx(Text, { size: "xs", variant: "secondary", children: "Video uploaded successfully. Large videos may take longer to process." })] })) : isImage(value) ? (_jsx(Div, { className: "relative aspect-video overflow-hidden rounded-lg", children: _jsx(MediaImage, { src: value, alt: label, size: "card", objectFit: "contain" }) })) : isPdf(value) ? (_jsxs(Div, { className: "space-y-2", children: [_jsx(Div, { className: "relative w-full overflow-hidden rounded-lg border border-zinc-200 dark:border-zinc-700", style: { height: 280 }, children: _jsx("iframe", { src: value, title: filenameFromUrl(value), className: "w-full h-full border-0" }) }), _jsxs(Row, { gap: "md", align: "center", children: [_jsx(Div, { "aria-hidden": true, className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-rose-100 text-rose-700 dark:bg-rose-900/40 dark:text-rose-300", children: _jsx("span", { className: "text-xs font-bold", children: "PDF" }) }), _jsx("a", { href: value, target: "_blank", rel: "noopener noreferrer", className: "text-sm font-medium text-blue-600 underline break-all dark:text-blue-400", children: filenameFromUrl(value) })] })] })) : (_jsx("a", { href: value, target: "_blank", rel: "noopener noreferrer", className: "text-sm underline break-all text-blue-600 dark:text-blue-400", children: filenameFromUrl(value) })), !disabled && (_jsxs(Row, { wrap: true, gap: "sm", className: "mt-2", children: [isVideo(value) && (enableTrim || enableThumbnail) && (_jsx(Button, { type: "button", onClick: () => onEditVideo(value), variant: "secondary", size: "sm", children: tMediaEditor("editVideo") })), _jsx(Button, { type: "button", onClick: onRemove, variant: "danger", size: "sm", children: tUpload("remove") })] }))] }));
84
+ return (_jsxs(Div, { className: `rounded-lg border border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-900 ${__P.p3}`, children: [isVideo(value) ? (_jsxs(Div, { className: "space-y-2", children: [_jsx(Div, { className: `relative aspect-video ${__O.hidden} rounded-lg`, children: _jsx(MediaVideo, { src: value, alt: label, controls: true, objectFit: "contain" }) }), _jsx(Text, { size: "xs", variant: "secondary", children: "Video uploaded successfully. Large videos may take longer to process." })] })) : isImage(value) ? (_jsx(Div, { className: `relative aspect-video ${__O.hidden} rounded-lg`, children: _jsx(MediaImage, { src: value, alt: label, size: "card", objectFit: "contain" }) })) : isPdf(value) ? (_jsxs(Div, { className: "space-y-2", children: [_jsx(Div, { className: `relative w-full ${__O.hidden} rounded-lg border border-zinc-200 dark:border-zinc-700`, style: { height: 280 }, children: _jsx("iframe", { src: value, title: filenameFromUrl(value), className: "w-full h-full border-0" }) }), _jsxs(Row, { gap: "md", align: "center", children: [_jsx(Div, { "aria-hidden": true, className: CLS_PDF_BADGE, children: _jsx(Span, { size: "xs", weight: "bold", children: "PDF" }) }), _jsx("a", { href: value, target: "_blank", rel: "noopener noreferrer", className: CLS_PDF_NAME, children: filenameFromUrl(value) })] })] })) : (_jsx("a", { href: value, target: "_blank", rel: "noopener noreferrer", className: CLS_PDF_LINK, children: filenameFromUrl(value) })), !disabled && (_jsxs(Row, { wrap: true, gap: "sm", className: "mt-2", children: [isVideo(value) && (enableTrim || enableThumbnail) && (_jsx(Button, { type: "button", onClick: () => onEditVideo(value), variant: "secondary", size: "sm", children: tMediaEditor("editVideo") })), _jsx(Button, { type: "button", onClick: onRemove, variant: "danger", size: "sm", children: tUpload("remove") })] }))] }));
76
85
  }
77
86
  export function MediaUploadField({ label, value, onChange, onChangeField, onUpload,
78
87
  // SB-UNI-Z5 2026-05-13 — `kind` derives accept/maxSizeMB when not set
@@ -5,6 +5,10 @@ import { Alert, Button, Div, Label, Spinner, Text } from "../../../ui";
5
5
  import { MediaImage } from "../MediaImage";
6
6
  import { MediaVideo } from "../MediaVideo";
7
7
  import { inferMediaTypeFromMime } from "../types/index";
8
+ const __O = {
9
+ hidden: "overflow-hidden",
10
+ };
11
+ const CLS_PDF_LINK = "text-sm underline break-all text-blue-600 dark:text-blue-400";
8
12
  function fileNameFromUrl(url) {
9
13
  try {
10
14
  const parts = new URL(url).pathname.split("/");
@@ -100,5 +104,5 @@ export function MediaUploadList({ label, value, onChange, onUpload, accept = "im
100
104
  unstageUrl(target.url);
101
105
  }
102
106
  };
103
- return (_jsxs(Div, { className: "space-y-2", children: [_jsx(Label, { className: "block text-sm font-medium text-zinc-600 dark:text-zinc-400", children: label }), value.length > 0 && (_jsx(Div, { className: "grid grid-cols-1 sm:grid-cols-2 gap-3", children: value.map((item, index) => (_jsxs(Div, { className: "rounded-lg border border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-900 p-3", children: [item.type === "video" ? (_jsx(Div, { className: "relative aspect-square max-h-24 overflow-hidden rounded-lg", children: _jsx(MediaVideo, { src: item.url, alt: item.alt || `Media ${index + 1}`, controls: true }) })) : item.type === "image" ? (_jsx(Div, { className: "relative aspect-square max-h-24 overflow-hidden rounded-lg", children: _jsx(MediaImage, { src: item.url, alt: item.alt || `Media ${index + 1}`, size: "card", objectFit: "contain" }) })) : (_jsx("a", { href: item.url, target: "_blank", rel: "noopener noreferrer", className: "text-sm underline break-all text-blue-600 dark:text-blue-400", children: fileNameFromUrl(item.url) })), !disabled && (_jsx(Div, { className: "mt-2", children: _jsx(Button, { type: "button", size: "sm", variant: "danger", onClick: () => removeAt(index), children: "Remove" }) }))] }, `${item.url}-${index}`))) })), !disabled && value.length < maxItems && (_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => inputRef.current?.click(), disabled: isLoading, children: isLoading ? "Uploading..." : `+ Add Files (${value.length}/${maxItems})` })), isLoading && (_jsxs(Div, { className: "flex items-center gap-2", children: [_jsx(Spinner, { size: "sm" }), _jsx(Text, { size: "sm", variant: "secondary", children: "Uploading" })] })), _jsx("input", { ref: inputRef, type: "file", multiple: true, accept: accept, onChange: handleFileChange, className: "hidden", "aria-hidden": "true", "data-testid": "media-upload-list-input" }), helperText && !error && (_jsx(Text, { variant: "secondary", size: "xs", children: helperText })), error && _jsx(Alert, { variant: "error", children: error })] }));
107
+ return (_jsxs(Div, { className: "space-y-2", children: [_jsx(Label, { className: "block text-sm font-medium text-zinc-600 dark:text-zinc-400", children: label }), value.length > 0 && (_jsx(Div, { className: "grid grid-cols-1 sm:grid-cols-2 gap-3", children: value.map((item, index) => (_jsxs(Div, { className: "rounded-lg border border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-900 p-3", children: [item.type === "video" ? (_jsx(Div, { className: `relative aspect-square max-h-24 ${__O.hidden} rounded-lg`, children: _jsx(MediaVideo, { src: item.url, alt: item.alt || `Media ${index + 1}`, controls: true }) })) : item.type === "image" ? (_jsx(Div, { className: `relative aspect-square max-h-24 ${__O.hidden} rounded-lg`, children: _jsx(MediaImage, { src: item.url, alt: item.alt || `Media ${index + 1}`, size: "card", objectFit: "contain" }) })) : (_jsx("a", { href: item.url, target: "_blank", rel: "noopener noreferrer", className: CLS_PDF_LINK, children: fileNameFromUrl(item.url) })), !disabled && (_jsx(Div, { className: "mt-2", children: _jsx(Button, { type: "button", size: "sm", variant: "danger", onClick: () => removeAt(index), children: "Remove" }) }))] }, `${item.url}-${index}`))) })), !disabled && value.length < maxItems && (_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => inputRef.current?.click(), disabled: isLoading, children: isLoading ? "Uploading..." : `+ Add Files (${value.length}/${maxItems})` })), isLoading && (_jsxs(Div, { className: "flex items-center gap-2", children: [_jsx(Spinner, { size: "sm" }), _jsx(Text, { size: "sm", variant: "secondary", children: "Uploading" })] })), _jsx("input", { ref: inputRef, type: "file", multiple: true, accept: accept, onChange: handleFileChange, className: "hidden", "aria-hidden": "true", "data-testid": "media-upload-list-input" }), helperText && !error && (_jsx(Text, { variant: "secondary", size: "xs", children: helperText })), error && _jsx(Alert, { variant: "error", children: error })] }));
104
108
  }