@mohasinac/appkit 2.8.2 → 2.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (451) hide show
  1. package/dist/_internal/client/features/classified/ClassifiedDetailView.js +7 -1
  2. package/dist/_internal/client/features/digital-code/CodeRevealPanel.js +4 -1
  3. package/dist/_internal/client/features/digital-code/DigitalCodeDetailView.js +7 -1
  4. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +3 -2
  5. package/dist/_internal/client/features/live/LiveItemDetailView.js +11 -2
  6. package/dist/_internal/client/scaffolds/AppShell.js +2 -1
  7. package/dist/_internal/client/scaffolds/DashboardScaffold.js +2 -1
  8. package/dist/_internal/server/features/checkout/actions.js +40 -39
  9. package/dist/_internal/shared/actions/action-registry.js +6 -0
  10. package/dist/_internal/shared/config/index.d.ts +1 -1
  11. package/dist/_internal/shared/config/schema.d.ts +0 -8
  12. package/dist/client-entry.d.ts +1 -1
  13. package/dist/client.d.ts +3 -1
  14. package/dist/client.js +3 -1
  15. package/dist/configs/next.js +12 -22
  16. package/dist/constants/api-endpoints.d.ts +6 -0
  17. package/dist/constants/api-endpoints.js +2 -0
  18. package/dist/features/about/components/AboutView.js +5 -2
  19. package/dist/features/about/components/FAQPageView.js +3 -3
  20. package/dist/features/about/components/FeesView.js +13 -5
  21. package/dist/features/about/components/HelpPageView.js +9 -5
  22. package/dist/features/about/components/HowAuctionsWorkView.js +9 -5
  23. package/dist/features/about/components/HowCheckoutWorksView.js +9 -5
  24. package/dist/features/about/components/HowOffersWorkView.js +10 -5
  25. package/dist/features/about/components/HowOrdersWorkView.js +10 -5
  26. package/dist/features/about/components/HowPayoutsWorkView.js +9 -5
  27. package/dist/features/about/components/HowPreOrdersWorkView.js +9 -5
  28. package/dist/features/about/components/HowReviewsWorkView.js +9 -5
  29. package/dist/features/about/components/PolicyPageView.js +3 -3
  30. package/dist/features/about/components/PublicProfileView.js +11 -4
  31. package/dist/features/about/components/SecurityPrivacyView.js +8 -4
  32. package/dist/features/about/components/ShippingPolicyView.js +3 -2
  33. package/dist/features/about/components/TrackOrderView.js +2 -2
  34. package/dist/features/about/components/UnauthorizedView.js +3 -3
  35. package/dist/features/account/components/AddressBook.js +1 -1
  36. package/dist/features/account/components/AddressForm.js +2 -2
  37. package/dist/features/account/components/AddressInlineSelect.d.ts +24 -0
  38. package/dist/features/account/components/AddressInlineSelect.js +78 -0
  39. package/dist/features/account/components/AddressSelectorCreate.d.ts +2 -1
  40. package/dist/features/account/components/AddressSelectorCreate.js +5 -32
  41. package/dist/features/account/components/AddressesIndexListing.js +3 -3
  42. package/dist/features/account/components/ChatWindow.js +2 -1
  43. package/dist/features/account/components/NotificationBell.js +13 -7
  44. package/dist/features/account/components/NotificationPreferencesPanel.js +4 -1
  45. package/dist/features/account/components/UserOffersPanel.js +2 -1
  46. package/dist/features/account/components/UserSidebar.js +11 -7
  47. package/dist/features/account/components/UserSupportView.js +13 -4
  48. package/dist/features/account/components/index.d.ts +2 -0
  49. package/dist/features/account/components/index.js +1 -0
  50. package/dist/features/addresses/repository/addresses.repository.d.ts +1 -0
  51. package/dist/features/addresses/repository/addresses.repository.js +13 -0
  52. package/dist/features/admin/components/AdminAdEditorView.js +8 -5
  53. package/dist/features/admin/components/AdminAddressEditorView.js +5 -5
  54. package/dist/features/admin/components/AdminAdsView.js +10 -7
  55. package/dist/features/admin/components/AdminAllEventEntriesView.js +5 -3
  56. package/dist/features/admin/components/AdminBidsView.js +6 -4
  57. package/dist/features/admin/components/AdminBlogEditorView.js +15 -9
  58. package/dist/features/admin/components/AdminBlogView.js +6 -4
  59. package/dist/features/admin/components/AdminBrandEditorView.js +10 -4
  60. package/dist/features/admin/components/AdminBrandsView.js +12 -10
  61. package/dist/features/admin/components/AdminBundleEditorView.js +4 -5
  62. package/dist/features/admin/components/AdminBundlesView.js +13 -11
  63. package/dist/features/admin/components/AdminCarouselEditorView.js +6 -3
  64. package/dist/features/admin/components/AdminCarouselView.js +6 -6
  65. package/dist/features/admin/components/AdminCartsView.js +6 -4
  66. package/dist/features/admin/components/AdminCatalogGuideView.js +2 -1
  67. package/dist/features/admin/components/AdminCategoriesView.js +12 -10
  68. package/dist/features/admin/components/AdminCategoryEditorView.js +11 -5
  69. package/dist/features/admin/components/AdminClassifiedView.js +4 -3
  70. package/dist/features/admin/components/AdminContactEditorView.js +8 -1
  71. package/dist/features/admin/components/AdminContactView.js +6 -4
  72. package/dist/features/admin/components/AdminCouponEditorView.js +23 -5
  73. package/dist/features/admin/components/AdminCouponsView.js +6 -4
  74. package/dist/features/admin/components/AdminDigitalCodesView.js +4 -3
  75. package/dist/features/admin/components/AdminEmployeeEditorView.js +7 -4
  76. package/dist/features/admin/components/AdminFaqEditorView.js +9 -3
  77. package/dist/features/admin/components/AdminFaqsView.js +9 -7
  78. package/dist/features/admin/components/AdminFeatureEditorView.js +7 -1
  79. package/dist/features/admin/components/AdminFeatureFlagsView.js +4 -1
  80. package/dist/features/admin/components/AdminFeaturesView.js +5 -4
  81. package/dist/features/admin/components/AdminFilterBar.js +4 -4
  82. package/dist/features/admin/components/AdminGroupedListingsView.js +66 -30
  83. package/dist/features/admin/components/AdminGuideHubView.js +4 -1
  84. package/dist/features/admin/components/AdminHistoryView.js +4 -3
  85. package/dist/features/admin/components/AdminLiveView.js +4 -3
  86. package/dist/features/admin/components/AdminMediaView.js +4 -1
  87. package/dist/features/admin/components/AdminNavigationView.js +7 -4
  88. package/dist/features/admin/components/AdminNewsletterView.js +5 -3
  89. package/dist/features/admin/components/AdminNotificationsView.js +8 -6
  90. package/dist/features/admin/components/AdminOrderEditorView.js +2 -2
  91. package/dist/features/admin/components/AdminOrdersView.js +6 -4
  92. package/dist/features/admin/components/AdminPageHeader.js +5 -2
  93. package/dist/features/admin/components/AdminPayoutsView.js +7 -5
  94. package/dist/features/admin/components/AdminPrizeDrawsView.js +11 -9
  95. package/dist/features/admin/components/AdminProductEditorView.js +12 -5
  96. package/dist/features/admin/components/AdminProductsView.js +11 -9
  97. package/dist/features/admin/components/AdminReturnRequestsView.js +4 -3
  98. package/dist/features/admin/components/AdminReviewsView.js +10 -8
  99. package/dist/features/admin/components/AdminScammerEditorView.js +6 -2
  100. package/dist/features/admin/components/AdminScammersView.js +11 -9
  101. package/dist/features/admin/components/AdminSectionsView.js +20 -22
  102. package/dist/features/admin/components/AdminSessionsManager.js +2 -1
  103. package/dist/features/admin/components/AdminSessionsView.js +8 -6
  104. package/dist/features/admin/components/AdminSidebar.js +11 -7
  105. package/dist/features/admin/components/AdminSiteConfigGuideView.js +2 -1
  106. package/dist/features/admin/components/AdminSiteSettingsView.js +5 -1
  107. package/dist/features/admin/components/AdminStoreAddressesView.js +4 -3
  108. package/dist/features/admin/components/AdminStoreEditorView.js +5 -5
  109. package/dist/features/admin/components/AdminStoresView.js +6 -4
  110. package/dist/features/admin/components/AdminSublistingCategoriesView.js +6 -5
  111. package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +3 -3
  112. package/dist/features/admin/components/AdminSupportTicketDetailView.js +10 -3
  113. package/dist/features/admin/components/AdminSupportTicketsView.js +11 -9
  114. package/dist/features/admin/components/AdminTeamView.js +6 -4
  115. package/dist/features/admin/components/AdminTrustGuideView.js +3 -3
  116. package/dist/features/admin/components/AdminUsersGuideView.js +3 -3
  117. package/dist/features/admin/components/AdminUsersView.js +6 -4
  118. package/dist/features/admin/components/AdminViewCards.js +12 -6
  119. package/dist/features/admin/components/AdminWishlistsView.js +4 -3
  120. package/dist/features/admin/components/BrandQuickCreateForm.js +2 -2
  121. package/dist/features/admin/components/CategoryQuickCreateForm.js +2 -2
  122. package/dist/features/admin/components/DashboardStats.js +9 -3
  123. package/dist/features/admin/components/DataListingView.js +3 -3
  124. package/dist/features/admin/components/DataTable.js +11 -7
  125. package/dist/features/admin/components/DrawerFormFooter.js +2 -2
  126. package/dist/features/admin/components/QuickEditMenu.js +2 -1
  127. package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +5 -1
  128. package/dist/features/admin/constants/filter-tabs.d.ts +1 -1
  129. package/dist/features/admin/constants/filter-tabs.js +0 -11
  130. package/dist/features/admin/types/index.d.ts +1 -1
  131. package/dist/features/auctions/actions/bid-actions.js +4 -2
  132. package/dist/features/auctions/components/AuctionBidsTable.js +4 -1
  133. package/dist/features/auctions/components/AuctionDetailPageView.js +14 -6
  134. package/dist/features/auctions/components/AuctionsListView.js +7 -6
  135. package/dist/features/auctions/components/CollapsibleBidHistory.js +5 -1
  136. package/dist/features/auctions/components/MarketplaceAuctionCard.js +9 -3
  137. package/dist/features/auctions/components/MarketplaceAuctionGrid.js +8 -2
  138. package/dist/features/auctions/components/PlaceBidFormClient.js +4 -1
  139. package/dist/features/auth/components/RegisterForm.js +2 -2
  140. package/dist/features/auth/components/VerifyEmailView.js +5 -2
  141. package/dist/features/before-after/components/BeforeAfterSlider.js +1 -1
  142. package/dist/features/blog/actions/blog-actions.js +3 -2
  143. package/dist/features/blog/components/BlogFeaturedCard.js +8 -1
  144. package/dist/features/blog/components/BlogIndexListing.js +11 -5
  145. package/dist/features/blog/components/BlogListView.js +11 -3
  146. package/dist/features/blog/components/BlogPostView.js +10 -3
  147. package/dist/features/cart/components/CartDrawer.js +11 -3
  148. package/dist/features/cart/components/CartSummary.js +2 -2
  149. package/dist/features/cart/components/CheckoutOtpModal.js +2 -1
  150. package/dist/features/categories/components/BrandDetailPageView.js +15 -10
  151. package/dist/features/categories/components/BrandDetailTabs.js +5 -1
  152. package/dist/features/categories/components/BundleDetailView.js +6 -3
  153. package/dist/features/categories/components/BundleDynamicRuleEditor.js +3 -1
  154. package/dist/features/categories/components/BundleItemsPicker.js +10 -3
  155. package/dist/features/categories/components/CategoriesIndexListing.js +13 -7
  156. package/dist/features/categories/components/CategoriesIndexPageView.js +5 -4
  157. package/dist/features/categories/components/CategoryBundlesListing.js +10 -6
  158. package/dist/features/categories/components/CategoryDetailPageView.js +18 -12
  159. package/dist/features/categories/components/CategoryDetailTabs.js +5 -1
  160. package/dist/features/categories/components/CategoryFilters.d.ts +12 -12
  161. package/dist/features/categories/components/CategoryFilters.js +13 -12
  162. package/dist/features/categories/components/CategoryForm.js +6 -3
  163. package/dist/features/categories/components/CategoryGrid.js +9 -2
  164. package/dist/features/categories/components/CategoryProductsListing.js +10 -4
  165. package/dist/features/categories/components/CategorySelectorCreate.js +3 -3
  166. package/dist/features/categories/components/CategorySortSelect.js +1 -1
  167. package/dist/features/categories/components/CategoryStoresListing.js +3 -3
  168. package/dist/features/categories/components/CategoryTableColumns.js +10 -6
  169. package/dist/features/categories/components/CategoryTree.d.ts +1 -1
  170. package/dist/features/categories/components/CategoryTree.js +2 -2
  171. package/dist/features/categories/schemas/firestore.d.ts +2 -2
  172. package/dist/features/checkout/actions/checkout-actions.d.ts +1 -1
  173. package/dist/features/checkout/actions/checkout-actions.js +1 -1
  174. package/dist/features/classified/components/ClassifiedFilters.js +2 -2
  175. package/dist/features/classified/components/ClassifiedIndexListing.js +9 -3
  176. package/dist/features/classified/components/ClassifiedListView.js +6 -5
  177. package/dist/features/collections/components/CollectionCard.js +2 -1
  178. package/dist/features/contact/components/ContactForm.js +4 -2
  179. package/dist/features/contact/components/ContactInfoSidebar.js +4 -1
  180. package/dist/features/copilot/components/AdminCopilotView.js +13 -5
  181. package/dist/features/cron/jobs/auction-expiry.job.d.ts +2 -2
  182. package/dist/features/cron/jobs/auction-expiry.job.js +2 -1
  183. package/dist/features/cron/jobs/preorder-reminder.job.d.ts +1 -1
  184. package/dist/features/cron/jobs/preorder-reminder.job.js +2 -1
  185. package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +9 -3
  186. package/dist/features/digital-codes/components/DigitalCodesListView.js +4 -3
  187. package/dist/features/events/actions/event-actions.js +6 -4
  188. package/dist/features/events/components/AdminEventEditorView.js +63 -41
  189. package/dist/features/events/components/AdminEventEntriesView.js +9 -6
  190. package/dist/features/events/components/AdminEventsView.js +7 -5
  191. package/dist/features/events/components/EventCard.js +7 -1
  192. package/dist/features/events/components/EventFilters.d.ts +4 -4
  193. package/dist/features/events/components/EventFilters.js +2 -2
  194. package/dist/features/events/components/EventFormDrawer.js +2 -1
  195. package/dist/features/events/components/EventLeaderboard.js +4 -4
  196. package/dist/features/events/components/EventOfferCard.js +4 -1
  197. package/dist/features/events/components/EventParticipateView.js +3 -2
  198. package/dist/features/events/components/EventPollWidget.js +6 -5
  199. package/dist/features/events/components/EventRaffleEntryForm.js +5 -2
  200. package/dist/features/events/components/EventRaffleWinnerView.js +7 -1
  201. package/dist/features/events/components/EventRafflesSection.js +6 -4
  202. package/dist/features/events/components/EventSaleBanner.js +5 -2
  203. package/dist/features/events/components/EventsIndexListing.js +8 -2
  204. package/dist/features/events/components/EventsListView.js +4 -1
  205. package/dist/features/events/components/SpinWheelView.js +7 -2
  206. package/dist/features/events/schemas/firestore.d.ts +1 -0
  207. package/dist/features/events/types/index.d.ts +1 -0
  208. package/dist/features/faq/actions/faq-actions.js +4 -2
  209. package/dist/features/faq/components/ContactCTA.js +4 -1
  210. package/dist/features/faq/components/FAQCategorySidebar.js +2 -2
  211. package/dist/features/faq/components/FAQHelpfulButtons.js +8 -5
  212. package/dist/features/faq/components/FAQPageContent.js +7 -6
  213. package/dist/features/faq/components/FAQSortDropdown.js +2 -2
  214. package/dist/features/filters/AsyncFacetSection.js +4 -2
  215. package/dist/features/filters/FilterFacetSection.js +14 -6
  216. package/dist/features/filters/RangeFilter.js +4 -2
  217. package/dist/features/filters/SwitchFilter.js +2 -1
  218. package/dist/features/forms/Checkbox.js +1 -1
  219. package/dist/features/forms/Radio.js +1 -1
  220. package/dist/features/forms/Slider.js +1 -1
  221. package/dist/features/homepage/components/AdSlot.js +4 -4
  222. package/dist/features/homepage/components/AdvertisementBanner.js +13 -4
  223. package/dist/features/homepage/components/AnnouncementBar.js +2 -1
  224. package/dist/features/homepage/components/BeforeAfterCard.js +8 -2
  225. package/dist/features/homepage/components/BrandsSection.js +6 -3
  226. package/dist/features/homepage/components/CTABannerSection.js +2 -2
  227. package/dist/features/homepage/components/CharacterHotspot.js +5 -2
  228. package/dist/features/homepage/components/CharacterHotspotForm.js +8 -4
  229. package/dist/features/homepage/components/CustomCardsSection.js +13 -7
  230. package/dist/features/homepage/components/CustomerReviewsSection.js +9 -3
  231. package/dist/features/homepage/components/FAQSection.js +7 -4
  232. package/dist/features/homepage/components/FeaturedBundlesSection.js +8 -2
  233. package/dist/features/homepage/components/FeaturedResultsSection.js +1 -1
  234. package/dist/features/homepage/components/GoogleReviewsSection.js +14 -8
  235. package/dist/features/homepage/components/HeroCarousel.js +1 -1
  236. package/dist/features/homepage/components/HomepageSkeleton.js +7 -1
  237. package/dist/features/homepage/components/HowItWorksInfoView.js +2 -2
  238. package/dist/features/homepage/components/HowItWorksSection.js +2 -2
  239. package/dist/features/homepage/components/MarketplaceHomepageView.js +4 -2
  240. package/dist/features/homepage/components/NewsletterBanner.js +3 -2
  241. package/dist/features/homepage/components/NewsletterSection.js +5 -2
  242. package/dist/features/homepage/components/PromoGrid.js +4 -1
  243. package/dist/features/homepage/components/SectionCarousel.js +7 -4
  244. package/dist/features/homepage/components/SecurityHighlightsSection.js +3 -3
  245. package/dist/features/homepage/components/ShopByCategorySection.js +10 -4
  246. package/dist/features/homepage/components/SiteFeaturesSection.js +5 -2
  247. package/dist/features/homepage/components/SocialFeedSection.js +4 -4
  248. package/dist/features/homepage/components/SocialPostCard.js +6 -3
  249. package/dist/features/homepage/components/TrustFeaturesSection.js +5 -5
  250. package/dist/features/homepage/components/TrustIndicatorsSection.js +5 -2
  251. package/dist/features/homepage/components/WelcomeSection.js +1 -1
  252. package/dist/features/homepage/components/WhatsAppCommunitySection.js +3 -3
  253. package/dist/features/layout/AppLayoutShell.js +2 -1
  254. package/dist/features/layout/BackToTop.js +1 -1
  255. package/dist/features/layout/BottomActions.js +4 -30
  256. package/dist/features/layout/BottomActionsContext.d.ts +0 -36
  257. package/dist/features/layout/BottomActionsContext.js +0 -36
  258. package/dist/features/layout/BottomNavItem.js +1 -1
  259. package/dist/features/layout/BottomSheet.js +4 -1
  260. package/dist/features/layout/FooterLayout.js +1 -1
  261. package/dist/features/layout/NavbarLayout.js +4 -1
  262. package/dist/features/layout/SidebarLayout.js +5 -2
  263. package/dist/features/live/components/LiveItemFilters.js +2 -2
  264. package/dist/features/live/components/LiveItemsIndexListing.js +9 -3
  265. package/dist/features/live/components/LiveItemsListView.js +6 -5
  266. package/dist/features/loyalty/components/CoinsDisplay.js +4 -2
  267. package/dist/features/media/AvatarUpload.js +2 -2
  268. package/dist/features/media/MediaLightbox.js +3 -2
  269. package/dist/features/media/modals/VideoThumbnailSelector.js +4 -1
  270. package/dist/features/media/modals/VideoTrimModal.js +1 -1
  271. package/dist/features/media/upload/CameraCapture.js +1 -1
  272. package/dist/features/media/upload/ImageUpload.js +4 -1
  273. package/dist/features/media/upload/MediaUploadField.js +11 -2
  274. package/dist/features/media/upload/MediaUploadList.js +5 -1
  275. package/dist/features/orders/components/MarketplaceOrderCard.js +2 -2
  276. package/dist/features/orders/components/OrdersList.js +2 -1
  277. package/dist/features/orders/components/RefundHistoryTable.js +4 -1
  278. package/dist/features/orders/components/RefundRequestView.js +2 -1
  279. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +5 -1
  280. package/dist/features/pre-orders/components/PreOrderActionsClient.js +3 -3
  281. package/dist/features/pre-orders/components/PreOrderBadge.js +2 -1
  282. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +16 -7
  283. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +32 -24
  284. package/dist/features/pre-orders/components/PreOrdersListView.js +5 -4
  285. package/dist/features/products/actions/product-actions.js +17 -15
  286. package/dist/features/products/columns/index.d.ts +1 -1
  287. package/dist/features/products/columns/index.js +1 -1
  288. package/dist/features/products/columns/productTableColumns.js +9 -4
  289. package/dist/features/products/components/AuctionsIndexListing.js +9 -3
  290. package/dist/features/products/components/BidHistory.js +4 -4
  291. package/dist/features/products/components/CompareOverlay.js +10 -2
  292. package/dist/features/products/components/CustomFieldsEditor.js +2 -1
  293. package/dist/features/products/components/CustomSectionTabContent.js +2 -2
  294. package/dist/features/products/components/CustomSectionsEditor.js +3 -2
  295. package/dist/features/products/components/GroupSettingsPanel.js +34 -26
  296. package/dist/features/products/components/MakeOfferButton.js +6 -2
  297. package/dist/features/products/components/MakeOfferForm.js +2 -1
  298. package/dist/features/products/components/MarketplaceBundleCard.js +6 -3
  299. package/dist/features/products/components/MarketplacePrizeDrawCard.js +3 -2
  300. package/dist/features/products/components/PlaceBidForm.js +2 -1
  301. package/dist/features/products/components/PrizeDrawCollage.js +6 -16
  302. package/dist/features/products/components/PrizeDrawDetailPageView.js +6 -1
  303. package/dist/features/products/components/PrizeDrawItemsEditor.js +4 -2
  304. package/dist/features/products/components/PrizeDrawsIndexListing.js +6 -3
  305. package/dist/features/products/components/PrizeDrawsListingView.js +5 -4
  306. package/dist/features/products/components/PrizeDrawsSection.js +6 -4
  307. package/dist/features/products/components/PrizeRevealModal.js +5 -1
  308. package/dist/features/products/components/ProductDetailPageView.js +32 -16
  309. package/dist/features/products/components/ProductFeatureBadges.js +9 -9
  310. package/dist/features/products/components/ProductForm.d.ts +11 -1
  311. package/dist/features/products/components/ProductForm.js +10 -5
  312. package/dist/features/products/components/ProductGalleryClient.js +8 -4
  313. package/dist/features/products/components/ProductGradingTab.js +4 -1
  314. package/dist/features/products/components/ProductGrid.js +35 -14
  315. package/dist/features/products/components/ProductInfo.js +2 -1
  316. package/dist/features/products/components/ProductTabs.js +2 -1
  317. package/dist/features/products/components/ProductTabsShell.js +5 -1
  318. package/dist/features/products/components/ProductsIndexListing.js +32 -24
  319. package/dist/features/products/components/ProductsIndexPageView.js +2 -2
  320. package/dist/features/products/components/RelatedProducts.js +3 -3
  321. package/dist/features/products/components/ShowGroupSection.js +10 -6
  322. package/dist/features/products/components/SublistingCarouselSection.js +7 -3
  323. package/dist/features/products/components/SublistingCategorySelect.d.ts +3 -1
  324. package/dist/features/products/components/SublistingCategorySelect.js +4 -37
  325. package/dist/features/products/constants/action-defs.js +3 -3
  326. package/dist/features/products/constants/sieve.d.ts +2 -2
  327. package/dist/features/products/constants/sieve.js +2 -2
  328. package/dist/features/products/hooks/useRelatedProducts.js +5 -4
  329. package/dist/features/promotions/components/CouponCard.js +5 -3
  330. package/dist/features/promotions/components/CouponsIndexListing.js +7 -3
  331. package/dist/features/promotions/repository/coupons.repository.d.ts +8 -0
  332. package/dist/features/promotions/repository/coupons.repository.js +2 -0
  333. package/dist/features/reviews/actions/review-actions.js +2 -1
  334. package/dist/features/reviews/components/ReviewDetailPageView.js +3 -3
  335. package/dist/features/reviews/components/ReviewDetailShell.js +15 -3
  336. package/dist/features/reviews/components/ReviewSummary.js +4 -2
  337. package/dist/features/reviews/components/ReviewsIndexListing.js +8 -2
  338. package/dist/features/reviews/components/ReviewsIndexPageView.js +7 -6
  339. package/dist/features/reviews/components/ReviewsList.js +1 -1
  340. package/dist/features/scams/actions/scam-actions.js +3 -2
  341. package/dist/features/scams/components/ScamAwarenessModal.js +2 -2
  342. package/dist/features/scams/components/ScamProfileView.js +3 -3
  343. package/dist/features/scams/components/ScamRegistryView.js +11 -8
  344. package/dist/features/search/actions/search-actions.js +7 -6
  345. package/dist/features/search/components/Search.js +9 -6
  346. package/dist/features/search/components/SearchFiltersRow.js +1 -1
  347. package/dist/features/search/components/SearchResultsSection.js +1 -1
  348. package/dist/features/seller/components/CouponInlineSelect.d.ts +22 -0
  349. package/dist/features/seller/components/CouponInlineSelect.js +104 -0
  350. package/dist/features/seller/components/GroupInlineSelect.d.ts +23 -0
  351. package/dist/features/seller/components/GroupInlineSelect.js +80 -0
  352. package/dist/features/seller/components/PhysicalLocationModal.js +2 -1
  353. package/dist/features/seller/components/PrintCenterView.js +2 -1
  354. package/dist/features/seller/components/ProductInlineSelect.d.ts +24 -0
  355. package/dist/features/seller/components/ProductInlineSelect.js +42 -0
  356. package/dist/features/seller/components/QuickProductForm.js +4 -1
  357. package/dist/features/seller/components/SellerAddressesView.js +8 -3
  358. package/dist/features/seller/components/SellerAnalyticsAlertsView.js +6 -3
  359. package/dist/features/seller/components/SellerAnalyticsView.js +2 -2
  360. package/dist/features/seller/components/SellerAuctionsView.js +7 -5
  361. package/dist/features/seller/components/SellerBidsView.js +12 -10
  362. package/dist/features/seller/components/SellerBundlesView.js +9 -7
  363. package/dist/features/seller/components/SellerClassifiedView.js +6 -5
  364. package/dist/features/seller/components/SellerCouponEditorView.d.ts +2 -0
  365. package/dist/features/seller/components/SellerCouponEditorView.js +15 -3
  366. package/dist/features/seller/components/SellerCouponsView.js +7 -5
  367. package/dist/features/seller/components/SellerDashboardView.js +2 -2
  368. package/dist/features/seller/components/SellerDigitalCodesView.js +7 -6
  369. package/dist/features/seller/components/SellerGoogleReviewsView.js +2 -2
  370. package/dist/features/seller/components/SellerGroupedListingsView.js +10 -9
  371. package/dist/features/seller/components/SellerLiveView.js +6 -5
  372. package/dist/features/seller/components/SellerOffersView.js +6 -4
  373. package/dist/features/seller/components/SellerOrdersView.js +18 -13
  374. package/dist/features/seller/components/SellerPayoutMethodsView.js +8 -6
  375. package/dist/features/seller/components/SellerPayoutRequestView.js +5 -1
  376. package/dist/features/seller/components/SellerPayoutSettingsView.js +5 -2
  377. package/dist/features/seller/components/SellerPayoutsView.js +6 -4
  378. package/dist/features/seller/components/SellerPreOrdersView.js +12 -10
  379. package/dist/features/seller/components/SellerPrizeDrawsView.js +12 -10
  380. package/dist/features/seller/components/SellerProductShell.js +1 -1
  381. package/dist/features/seller/components/SellerProductsCards.js +4 -1
  382. package/dist/features/seller/components/SellerProductsView.js +14 -12
  383. package/dist/features/seller/components/SellerReviewsView.js +7 -3
  384. package/dist/features/seller/components/SellerShippingConfigsView.js +7 -6
  385. package/dist/features/seller/components/SellerShippingView.js +1 -1
  386. package/dist/features/seller/components/SellerSidebar.js +15 -8
  387. package/dist/features/seller/components/SellerStoreCategoriesView.js +5 -4
  388. package/dist/features/seller/components/SellerStorefrontView.js +2 -2
  389. package/dist/features/seller/components/SellerTemplatesView.js +11 -7
  390. package/dist/features/seller/components/SublistingInlineSelect.d.ts +19 -0
  391. package/dist/features/seller/components/SublistingInlineSelect.js +84 -0
  392. package/dist/features/seller/components/analytics/SellerTopProducts.js +1 -1
  393. package/dist/features/seller/components/index.d.ts +8 -0
  394. package/dist/features/seller/components/index.js +4 -0
  395. package/dist/features/shell/FormShell.js +10 -2
  396. package/dist/features/shell/QuickFormDrawer.js +5 -5
  397. package/dist/features/shell/StepForm.js +6 -6
  398. package/dist/features/site-settings/components/ActionPermissionsManager.js +8 -4
  399. package/dist/features/site-settings/components/NavPermissionsManager.js +7 -4
  400. package/dist/features/stores/actions/store-query-actions.js +3 -2
  401. package/dist/features/stores/components/InteractiveStoreCard.js +5 -1
  402. package/dist/features/stores/components/StoreAboutView.js +4 -1
  403. package/dist/features/stores/components/StoreAddressSelectorCreate.d.ts +2 -1
  404. package/dist/features/stores/components/StoreAddressSelectorCreate.js +5 -31
  405. package/dist/features/stores/components/StoreAuctionsListing.js +6 -3
  406. package/dist/features/stores/components/StoreAuctionsPageView.js +4 -2
  407. package/dist/features/stores/components/StoreDetailLayoutView.d.ts +1 -1
  408. package/dist/features/stores/components/StoreDetailLayoutView.js +7 -6
  409. package/dist/features/stores/components/StoreGuideHubView.js +5 -2
  410. package/dist/features/stores/components/StoreHeader.js +8 -1
  411. package/dist/features/stores/components/StorePreOrdersListing.js +6 -3
  412. package/dist/features/stores/components/StorePreOrdersPageView.js +4 -2
  413. package/dist/features/stores/components/StorePrizeDrawsPageView.js +4 -2
  414. package/dist/features/stores/components/StoreProductsListing.js +6 -3
  415. package/dist/features/stores/components/StoreProductsPageView.js +2 -1
  416. package/dist/features/stores/components/StoreProductsView.js +5 -4
  417. package/dist/features/stores/components/StoreReviewsListing.js +8 -2
  418. package/dist/features/stores/components/StoresIndexListing.js +16 -9
  419. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +7 -1
  420. package/dist/features/whatsapp-bot/components/WhatsAppChatButton.js +2 -1
  421. package/dist/features/wishlist/components/WishlistPage.js +2 -1
  422. package/dist/features/wishlist/components/WishlistView.js +4 -3
  423. package/dist/index.d.ts +10 -0
  424. package/dist/index.js +13 -1
  425. package/dist/next/components/GlobalError.js +2 -2
  426. package/dist/next/routing/route-map.d.ts +2 -0
  427. package/dist/next/routing/route-map.js +1 -0
  428. package/dist/react/ErrorBoundary.js +2 -2
  429. package/dist/styles.css +2 -1
  430. package/dist/tailwind-utilities.css +1 -1
  431. package/dist/ui/DataTable.js +17 -16
  432. package/dist/ui/components/DateInput.js +2 -2
  433. package/dist/ui/components/DetailPageGallery.js +4 -1
  434. package/dist/ui/components/DetailPageTabs.js +6 -2
  435. package/dist/ui/components/ImageLightbox.js +5 -3
  436. package/dist/ui/components/Input.js +6 -3
  437. package/dist/ui/components/Layout.d.ts +4 -0
  438. package/dist/ui/components/Layout.js +1 -1
  439. package/dist/ui/components/Layout.style.css +1 -0
  440. package/dist/ui/components/ListingFilterDrawer.js +4 -1
  441. package/dist/ui/components/ListingLayout.js +9 -8
  442. package/dist/ui/components/ListingToolbar.js +5 -1
  443. package/dist/ui/components/PaginatedSelect.d.ts +1 -2
  444. package/dist/ui/components/PaginatedSelect.js +1 -2
  445. package/dist/ui/components/Radio.js +1 -1
  446. package/dist/ui/components/Select.js +2 -1
  447. package/dist/ui/components/Slider.js +1 -1
  448. package/dist/ui/components/VacationBanner.js +2 -1
  449. package/dist/ui/components/surface-tokens.d.ts +1 -0
  450. package/dist/ui/components/surface-tokens.js +1 -0
  451. package/package.json +11 -2
@@ -1,5 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Article, ClaimCouponButton, Div, Heading, Span, Text, TextLink } from "../../../ui";
3
+ const __P = {
4
+ p4: "p-4",
5
+ };
6
+ const CLS_PANEL = "rounded-2xl border border-amber-200 bg-amber-50/60 dark:border-amber-700 dark:bg-amber-900/20 p-6 space-y-3";
7
+ const CLS_LABEL = "text-xs uppercase tracking-wide text-amber-700 dark:text-amber-300";
8
+ const CLS_WINNER_NAME = "mt-1 text-2xl font-bold text-amber-900 dark:text-amber-100";
3
9
  const DEFAULT_LABELS = {
4
10
  heading: "Raffle Winner",
5
11
  winnerLabel: "Winner",
@@ -14,5 +20,5 @@ export function EventRaffleWinnerView({ event, currentUserIsWinner, labels }) {
14
20
  if (!event.raffleWinnerUserId) {
15
21
  return (_jsx(Div, { className: "rounded-xl border border-dashed border-zinc-300 dark:border-zinc-700 px-6 py-10 text-center", children: _jsx(Text, { className: "text-zinc-500 dark:text-zinc-400", children: l.notDrawnYet }) }));
16
22
  }
17
- return (_jsxs(Article, { className: "space-y-4", children: [_jsxs(Heading, { level: 2, className: "text-xl font-semibold text-zinc-900 dark:text-zinc-100", children: ["\uD83C\uDF9F\uFE0F ", l.heading] }), _jsxs(Div, { className: "rounded-2xl border border-amber-200 bg-amber-50/60 dark:border-amber-700 dark:bg-amber-900/20 p-6 space-y-3", children: [_jsxs(Div, { children: [_jsx(Text, { className: "text-xs uppercase tracking-wide text-amber-700 dark:text-amber-300", children: l.winnerLabel }), _jsx(Text, { className: "mt-1 text-2xl font-bold text-amber-900 dark:text-amber-100", children: event.raffleWinnerDisplayName?.trim() || l.anonymous })] }), event.rafflePrize ? (_jsxs(Div, { children: [_jsx(Text, { className: "text-xs uppercase tracking-wide text-amber-700 dark:text-amber-300", children: l.prizeLabel }), _jsx(Text, { className: "mt-1 text-base text-zinc-800 dark:text-zinc-100", children: event.rafflePrize })] })) : null, currentUserIsWinner && event.rafflePrizeCouponCode ? (_jsx(Div, { className: "pt-2", children: _jsx(ClaimCouponButton, { couponCode: event.rafflePrizeCouponCode, source: "raffle", size: "sm" }) })) : null, _jsxs(Div, { className: "flex flex-wrap gap-x-6 gap-y-2 pt-2 text-sm text-zinc-600 dark:text-zinc-300", children: [typeof event.raffleEntryCount === "number" ? (_jsxs(Span, { children: [l.poolLabel, ":", " ", _jsx(Span, { className: "font-medium text-zinc-900 dark:text-zinc-100", children: event.raffleEntryCount })] })) : null, event.raffleTriggeredAt ? (_jsx(Span, { children: new Date(event.raffleTriggeredAt).toLocaleString() })) : null] })] }), event.raffleGithubFunctionUrl ? (_jsxs(Div, { className: "rounded-lg border border-zinc-200 dark:border-zinc-700 p-4 text-sm", children: [_jsx(Text, { className: "font-medium text-zinc-700 dark:text-zinc-200", children: l.fairnessLabel }), _jsx(TextLink, { href: event.raffleGithubFunctionUrl, className: "mt-1 block break-all text-primary-600 dark:text-primary-400 hover:underline", children: event.raffleGithubFunctionUrl })] })) : null] }));
23
+ return (_jsxs(Article, { className: "space-y-4", children: [_jsxs(Heading, { level: 2, className: "text-xl font-semibold text-zinc-900 dark:text-zinc-100", children: ["\uD83C\uDF9F\uFE0F ", l.heading] }), _jsxs(Div, { className: CLS_PANEL, children: [_jsxs(Div, { children: [_jsx(Text, { className: CLS_LABEL, children: l.winnerLabel }), _jsx(Text, { className: CLS_WINNER_NAME, children: event.raffleWinnerDisplayName?.trim() || l.anonymous })] }), event.rafflePrize ? (_jsxs(Div, { children: [_jsx(Text, { className: CLS_LABEL, children: l.prizeLabel }), _jsx(Text, { className: "mt-1 text-base text-zinc-800 dark:text-zinc-100", children: event.rafflePrize })] })) : null, currentUserIsWinner && event.rafflePrizeCouponCode ? (_jsx(Div, { className: "pt-2", children: _jsx(ClaimCouponButton, { couponCode: event.rafflePrizeCouponCode, source: "raffle", size: "sm" }) })) : null, _jsxs(Div, { className: "flex flex-wrap gap-x-6 gap-y-2 pt-2 text-sm text-zinc-600 dark:text-zinc-300", children: [typeof event.raffleEntryCount === "number" ? (_jsxs(Span, { children: [l.poolLabel, ":", " ", _jsx(Span, { weight: "medium", className: "text-zinc-900 dark:text-zinc-100", children: event.raffleEntryCount })] })) : null, event.raffleTriggeredAt ? (_jsx(Span, { children: new Date(event.raffleTriggeredAt).toLocaleString() })) : null] })] }), event.raffleGithubFunctionUrl ? (_jsxs(Div, { className: `rounded-lg border border-zinc-200 dark:border-zinc-700 ${__P.p4} text-sm`, children: [_jsx(Text, { className: "font-medium text-zinc-700 dark:text-zinc-200", children: l.fairnessLabel }), _jsx(TextLink, { href: event.raffleGithubFunctionUrl, className: "mt-1 block break-all text-primary-600 dark:text-primary-400 hover:underline", children: event.raffleGithubFunctionUrl })] })) : null] }));
18
24
  }
@@ -1,6 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { sieveFilter, sieveAnd, SIEVE_OP } from "@mohasinac/appkit";
3
+ import { sortBy } from "@mohasinac/appkit";
2
4
  import Link from "next/link";
3
- import { Container, Heading, Section, Stack, Text, } from "../../../ui";
5
+ import { Container, Div, Heading, Section, Stack, Text, } from "../../../ui";
4
6
  import { ROUTES } from "../../../next";
5
7
  import { eventRepository } from "../repository/events.repository";
6
8
  import { EventCard } from "./EventCard";
@@ -15,8 +17,8 @@ export async function EventRafflesSection({ config, }) {
15
17
  let events = [];
16
18
  try {
17
19
  const result = await eventRepository.list({
18
- filters: "hasRaffle==true,status==active",
19
- sorts: "-startsAt",
20
+ filters: sieveAnd(sieveFilter("hasRaffle", SIEVE_OP.EQ, "true"), sieveFilter("status", SIEVE_OP.EQ, "active")),
21
+ sorts: sortBy("startsAt", "DESC"),
20
22
  pageSize: limit,
21
23
  });
22
24
  events = (result.items ?? []);
@@ -24,5 +26,5 @@ export async function EventRafflesSection({ config, }) {
24
26
  catch {
25
27
  events = [];
26
28
  }
27
- return (_jsx(Section, { className: "py-10", children: _jsx(Container, { size: "xl", children: _jsxs(Stack, { gap: "md", children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 2, className: "text-2xl font-semibold text-zinc-900 dark:text-zinc-50", children: title }), subtitle ? (_jsx(Text, { className: "text-sm text-zinc-500 dark:text-zinc-400", children: subtitle })) : null] }), events.length === 0 ? (_jsxs(Stack, { align: "center", gap: "sm", className: "rounded-2xl border border-dashed border-zinc-300 px-6 py-12 text-center dark:border-slate-700", children: [_jsx(Text, { className: "text-sm text-zinc-500 dark:text-zinc-400", children: "No upcoming raffles \u2014 keep an eye on the events page." }), _jsx(Link, { href: String(ROUTES.PUBLIC.EVENTS), className: "text-sm font-medium text-primary hover:underline", children: "Browse all events \u2192" })] })) : (_jsx("div", { className: "fluid-grid-card gap-3", children: events.map((event) => (_jsx(EventCard, { event: event }, event.id))) }))] }) }) }));
29
+ return (_jsx(Section, { className: "py-10", children: _jsx(Container, { size: "xl", children: _jsxs(Stack, { gap: "md", children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 2, className: "text-2xl font-semibold text-zinc-900 dark:text-zinc-50", children: title }), subtitle ? (_jsx(Text, { className: "text-sm text-zinc-500 dark:text-zinc-400", children: subtitle })) : null] }), events.length === 0 ? (_jsxs(Stack, { align: "center", gap: "sm", className: "rounded-2xl border border-dashed border-zinc-300 px-6 py-12 text-center dark:border-slate-700", children: [_jsx(Text, { className: "text-sm text-zinc-500 dark:text-zinc-400", children: "No upcoming raffles \u2014 keep an eye on the events page." }), _jsx(Link, { href: String(ROUTES.PUBLIC.EVENTS), className: "text-sm font-medium text-primary hover:underline", children: "Browse all events \u2192" })] })) : (_jsx(Div, { className: "fluid-grid-card gap-3", children: events.map((event) => (_jsx(EventCard, { event: event }, event.id))) }))] }) }) }));
28
30
  }
@@ -1,9 +1,12 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import Link from "next/link";
4
- import { Div, Heading, Stack, Text } from "../../../ui";
4
+ import { Div, Heading, Span, Stack, Text } from "../../../ui";
5
5
  import { Button } from "../../../ui/components/Button";
6
6
  import { ROUTES } from "../../../next/routing/route-map";
7
+ const __P = {
8
+ p6: "p-6",
9
+ };
7
10
  /**
8
11
  * `EventSaleBanner` — W1-18 — sale event UI noted as missing in the plan.
9
12
  * Renders a hero banner with the discount, optional coupon, and a CTA to the
@@ -14,5 +17,5 @@ export function EventSaleBanner({ discountPercent, couponCode, title, subtitle,
14
17
  const href = filterParam
15
18
  ? `${ROUTES.PUBLIC.PRODUCTS}?${encodeURIComponent(filterParam.key)}=${encodeURIComponent(filterParam.value)}`
16
19
  : `${ROUTES.PUBLIC.PRODUCTS}?onSale=true`;
17
- return (_jsx(Div, { className: "rounded-2xl bg-gradient-to-br from-[var(--appkit-color-primary)] to-[var(--appkit-color-secondary)] p-6 text-white shadow-lg", children: _jsxs(Stack, { gap: "md", children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 2, className: "text-3xl font-bold", children: headline }), subtitle ? _jsx(Text, { className: "text-base text-white/90", children: subtitle }) : null] }), couponCode ? (_jsxs(Div, { className: "inline-flex items-center gap-3 rounded-lg bg-white/10 px-4 py-2 backdrop-blur", children: [_jsx("span", { className: "text-xs uppercase tracking-wide opacity-80", children: "Code" }), _jsx("span", { className: "font-mono text-lg font-bold", children: couponCode })] })) : null, _jsx(Div, { children: _jsx(Link, { href: href, children: _jsx(Button, { variant: "secondary", children: "Shop the sale" }) }) })] }) }));
20
+ return (_jsx(Div, { className: `rounded-2xl bg-gradient-to-br from-[var(--appkit-color-primary)] to-[var(--appkit-color-secondary)] ${__P.p6} text-white shadow-lg`, children: _jsxs(Stack, { gap: "md", children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 2, className: "text-3xl font-bold", children: headline }), subtitle ? _jsx(Text, { className: "text-base text-white/90", children: subtitle }) : null] }), couponCode ? (_jsxs(Div, { className: "inline-flex items-center gap-3 rounded-lg bg-white/10 px-4 py-2 backdrop-blur", children: [_jsx(Span, { size: "xs", className: "uppercase tracking-wide opacity-80", children: "Code" }), _jsx(Span, { size: "lg", weight: "bold", className: "font-mono", children: couponCode })] })) : null, _jsx(Div, { children: _jsx(Link, { href: href, children: _jsx(Button, { variant: "secondary", children: "Shop the sale" }) }) })] }) }));
18
21
  }
@@ -3,13 +3,19 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useCallback, useMemo } from "react";
4
4
  import { useUrlTable } from "../../../react/hooks/useUrlTable";
5
5
  import { useEvents } from "../hooks/useEvents";
6
- import { ListingFilterDrawer, ListingToolbar, Pagination, Text } from "../../../ui";
6
+ import { Div, ListingFilterDrawer, ListingToolbar, Pagination, Text } from "../../../ui";
7
7
  import { EventCard } from "./EventCard";
8
8
  import { EventFilters, EVENT_PUBLIC_SORT_OPTIONS } from "./EventFilters";
9
9
  import { EVENT_FIELDS } from "../../../constants/field-names";
10
10
  import { sieveFilter, sieveMultiEq, sieveAnd, SIEVE_OP } from "../../../utils/sieve-builder";
11
11
  import { TABLE_KEYS, VIEW_MODE } from "../../../constants/table-keys";
12
12
  import { sortBy } from "../../../constants/sort";
13
+ const __P = {
14
+ p4: "p-4",
15
+ };
16
+ const __O = {
17
+ hidden: "overflow-hidden",
18
+ };
13
19
  const PAGE_SIZE = 24;
14
20
  const FILTER_KEYS = [TABLE_KEYS.TYPE, TABLE_KEYS.STATUS, TABLE_KEYS.DATE_FROM, TABLE_KEYS.DATE_TO, TABLE_KEYS.SHOW_EXPIRED];
15
21
  export function EventsIndexListing({ initialData }) {
@@ -115,5 +121,5 @@ export function EventsIndexListing({ initialData }) {
115
121
  const commitSearch = useCallback(() => {
116
122
  table.set(TABLE_KEYS.QUERY, searchInput.trim());
117
123
  }, [searchInput, table]);
118
- return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search events...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get(TABLE_KEYS.SORT) || sortBy(EVENT_FIELDS.STARTS_AT, "ASC"), sortOptions: EVENT_PUBLIC_SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, view: view, onViewChange: handleViewToggle, onResetAll: resetAll, hasActiveState: hasActiveState }), 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: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsx("div", { className: "py-6", children: isLoading ? (_jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6", children: Array.from({ length: 6 }).map((_, i) => (_jsxs("div", { className: "rounded-xl border border-zinc-100 dark:border-slate-700 overflow-hidden animate-pulse", children: [_jsx("div", { className: "aspect-video bg-zinc-200 dark:bg-slate-700" }), _jsxs("div", { className: "p-4 space-y-2", children: [_jsx("div", { className: "h-4 bg-zinc-200 dark:bg-slate-700 rounded w-3/4" }), _jsx("div", { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-full" }), _jsx("div", { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-2/3" }), _jsx("div", { className: "h-8 bg-zinc-200 dark:bg-slate-700 rounded mt-2" })] })] }, i))) })) : events.length === 0 ? (_jsx(Text, { className: "py-12 text-center text-sm text-zinc-500 dark:text-zinc-400", children: "No events found." })) : view === "list" ? (_jsx("div", { className: "flex flex-col divide-y divide-zinc-100 dark:divide-zinc-800 rounded-xl border border-zinc-100 dark:border-zinc-800", children: events.map((event) => (_jsx(EventCard, { event: event }, event.id))) })) : (_jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6", children: events.map((event) => (_jsx(EventCard, { event: event }, event.id))) })) }), _jsx(ListingFilterDrawer, { open: filterOpen, onClose: () => setFilterOpen(false), onApply: applyFilters, onClear: clearFilters, activeCount: activeFilterCount, children: _jsx(EventFilters, { table: pendingTable, variant: "public" }) })] }));
124
+ return (_jsxs(Div, { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search events...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get(TABLE_KEYS.SORT) || sortBy(EVENT_FIELDS.STARTS_AT, "ASC"), sortOptions: EVENT_PUBLIC_SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, view: view, onViewChange: handleViewToggle, onResetAll: resetAll, hasActiveState: hasActiveState }), 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: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsx(Div, { className: "py-6", children: isLoading ? (_jsx(Div, { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6", children: Array.from({ length: 6 }).map((_, i) => (_jsxs(Div, { className: `rounded-xl border border-zinc-100 dark:border-slate-700 ${__O.hidden} animate-pulse`, children: [_jsx(Div, { className: "aspect-video bg-zinc-200 dark:bg-slate-700" }), _jsxs(Div, { className: `${__P.p4} space-y-2`, children: [_jsx(Div, { className: "h-4 bg-zinc-200 dark:bg-slate-700 rounded w-3/4" }), _jsx(Div, { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-full" }), _jsx(Div, { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-2/3" }), _jsx(Div, { className: "h-8 bg-zinc-200 dark:bg-slate-700 rounded mt-2" })] })] }, i))) })) : events.length === 0 ? (_jsx(Text, { className: "py-12 text-center text-sm text-zinc-500 dark:text-zinc-400", children: "No events found." })) : view === "list" ? (_jsx(Div, { className: "flex flex-col divide-y divide-zinc-100 dark:divide-zinc-800 rounded-xl border border-zinc-100 dark:border-zinc-800", children: events.map((event) => (_jsx(EventCard, { event: event }, event.id))) })) : (_jsx(Div, { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6", children: events.map((event) => (_jsx(EventCard, { event: event }, event.id))) })) }), _jsx(ListingFilterDrawer, { open: filterOpen, onClose: () => setFilterOpen(false), onApply: applyFilters, onClear: clearFilters, activeCount: activeFilterCount, children: _jsx(EventFilters, { table: pendingTable, variant: "public" }) })] }));
119
125
  }
@@ -2,9 +2,12 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import React from "react";
3
3
  import { Div, Pagination, Text } from "../../../ui";
4
4
  import { EventCard } from "./EventCard";
5
+ const __P = {
6
+ p4: "p-4",
7
+ };
5
8
  export function EventsListView({ events, isLoading, totalPages = 1, currentPage = 1, total = 0, onPageChange, onParticipate, emptyLabel = "No events found", slots, }) {
6
9
  if (isLoading) {
7
- return (_jsx(Div, { className: "grid gap-6 sm:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsxs(Div, { className: "animate-pulse overflow-hidden rounded-xl border border-zinc-200 dark:border-zinc-700 bg-zinc-100 dark:bg-zinc-800", children: [_jsx(Div, { className: "aspect-video bg-zinc-200 dark:bg-zinc-700" }), _jsxs(Div, { className: "space-y-2 p-4", children: [_jsx(Div, { className: "h-4 w-16 rounded bg-zinc-200 dark:bg-zinc-700" }), _jsx(Div, { className: "h-5 w-full rounded bg-zinc-200 dark:bg-zinc-700" }), _jsx(Div, { className: "h-4 w-3/4 rounded bg-zinc-200 dark:bg-zinc-700" })] })] }, i))) }));
10
+ return (_jsx(Div, { className: "grid gap-6 sm:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsxs(Div, { className: "animate-pulse overflow-hidden rounded-xl border border-zinc-200 dark:border-zinc-700 bg-zinc-100 dark:bg-zinc-800", children: [_jsx(Div, { className: "aspect-video bg-zinc-200 dark:bg-zinc-700" }), _jsxs(Div, { className: `space-y-2 ${__P.p4}`, children: [_jsx(Div, { className: "h-4 w-16 rounded bg-zinc-200 dark:bg-zinc-700" }), _jsx(Div, { className: "h-5 w-full rounded bg-zinc-200 dark:bg-zinc-700" }), _jsx(Div, { className: "h-4 w-3/4 rounded bg-zinc-200 dark:bg-zinc-700" })] })] }, i))) }));
8
11
  }
9
12
  if (events.length === 0) {
10
13
  if (slots?.renderEmptyState) {
@@ -3,6 +3,11 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  import { useCallback, useMemo, useState } from "react";
4
4
  import { Button, ClaimCouponButton, Div, Heading, LoginRequiredModal, Span, Text, useToast } from "../../../ui";
5
5
  import { isAuthError } from "../../../utils/auth-error";
6
+ const CLS_WHEEL = "relative mx-auto aspect-square w-64 overflow-hidden rounded-full border-4 border-amber-400 bg-gradient-to-br from-amber-100 via-rose-100 to-violet-100 dark:from-amber-900/40 dark:via-rose-900/40 dark:to-violet-900/40";
7
+ const CLS_PRIZE_BOX = "rounded-xl border border-emerald-300 bg-success-surface dark:border-emerald-700 p-4 text-center";
8
+ const CLS_PRIZE_TITLE = "mt-1 text-lg font-bold text-emerald-900 dark:text-emerald-100";
9
+ const CLS_PRIZE_BODY = "mt-2 text-sm text-emerald-800 dark:text-emerald-200";
10
+ const CLS_ERROR_TEXT = "text-sm text-rose-600 dark:text-rose-400 text-center";
6
11
  const DEFAULT_LABELS = {
7
12
  heading: "Spin the Wheel",
8
13
  spinButton: "Spin",
@@ -60,7 +65,7 @@ export function SpinWheelView({ eventId, prizes, alreadyUsed, initialPrizeId, in
60
65
  const wonPrize = resultPrizeId
61
66
  ? activePrizes.find((p) => p.id === resultPrizeId)
62
67
  : undefined;
63
- return (_jsxs(Div, { className: "space-y-4", children: [_jsx(LoginRequiredModal, { isOpen: showLoginModal, onClose: () => setShowLoginModal(false), message: "You need to be signed in to spin the wheel. Please log in or create an account to continue." }), _jsxs(Heading, { level: 2, className: "text-xl font-semibold text-zinc-900 dark:text-zinc-100", children: ["\uD83C\uDFA1 ", l.heading] }), _jsxs(Div, { className: "relative mx-auto aspect-square w-64 overflow-hidden rounded-full border-4 border-amber-400 bg-gradient-to-br from-amber-100 via-rose-100 to-violet-100 dark:from-amber-900/40 dark:via-rose-900/40 dark:to-violet-900/40", "aria-label": "Spin wheel", children: [_jsx(Div, { className: "absolute inset-0 flex items-center justify-center", style: {
68
+ return (_jsxs(Div, { className: "space-y-4", children: [_jsx(LoginRequiredModal, { isOpen: showLoginModal, onClose: () => setShowLoginModal(false), message: "You need to be signed in to spin the wheel. Please log in or create an account to continue." }), _jsxs(Heading, { level: 2, className: "text-xl font-semibold text-zinc-900 dark:text-zinc-100", children: ["\uD83C\uDFA1 ", l.heading] }), _jsxs(Div, { className: CLS_WHEEL, "aria-label": "Spin wheel", children: [_jsx(Div, { className: "absolute inset-0 flex items-center justify-center", style: {
64
69
  animation: spinning
65
70
  ? `lir-spin ${ANIMATION_MS}ms cubic-bezier(0.2, 0.8, 0.2, 1)`
66
71
  : undefined,
@@ -69,5 +74,5 @@ export function SpinWheelView({ eventId, prizes, alreadyUsed, initialPrizeId, in
69
74
  0% { transform: rotate(0deg); }
70
75
  100% { transform: rotate(2160deg); }
71
76
  }
72
- ` })] }), wonPrize ? (_jsxs(Div, { className: "rounded-xl border border-emerald-300 bg-success-surface dark:border-emerald-700 p-4 text-center", children: [_jsx(Text, { className: "text-sm uppercase tracking-wide text-success", children: l.wonHeadline }), _jsx(Text, { className: "mt-1 text-lg font-bold text-emerald-900 dark:text-emerald-100", children: wonPrize.label }), resultCoupon ? (_jsxs(_Fragment, { children: [_jsxs(Text, { className: "mt-2 text-sm text-emerald-800 dark:text-emerald-200", children: [l.couponHint, " ", _jsx(Span, { className: "font-mono font-semibold", children: resultCoupon })] }), _jsx(Div, { className: "mt-3 flex justify-center", children: _jsx(ClaimCouponButton, { couponCode: resultCoupon, size: "sm", source: "spin" }) })] })) : null] })) : null, error ? (_jsx(Text, { className: "text-sm text-rose-600 dark:text-rose-400 text-center", children: error })) : null, _jsx(Div, { className: "flex justify-center", children: _jsx(Button, { variant: "primary", size: "lg", onClick: handleSpin, disabled: disabled, children: spinning ? l.spinningButton : l.spinButton }) }), alreadyUsed ? (_jsx(Text, { className: "text-center text-sm text-zinc-500 dark:text-zinc-400", children: l.alreadySpun })) : !inWindow ? (_jsx(Text, { className: "text-center text-sm text-zinc-500 dark:text-zinc-400", children: l.outsideWindow })) : null] }));
77
+ ` })] }), wonPrize ? (_jsxs(Div, { className: CLS_PRIZE_BOX, children: [_jsx(Text, { className: "text-sm uppercase tracking-wide text-success", children: l.wonHeadline }), _jsx(Text, { className: CLS_PRIZE_TITLE, children: wonPrize.label }), resultCoupon ? (_jsxs(_Fragment, { children: [_jsxs(Text, { className: CLS_PRIZE_BODY, children: [l.couponHint, " ", _jsx(Span, { weight: "semibold", className: "font-mono", children: resultCoupon })] }), _jsx(Div, { className: "mt-3 flex justify-center", children: _jsx(ClaimCouponButton, { couponCode: resultCoupon, size: "sm", source: "spin" }) })] })) : null] })) : null, error ? (_jsx(Text, { className: CLS_ERROR_TEXT, children: error })) : null, _jsx(Div, { className: "flex justify-center", children: _jsx(Button, { variant: "primary", size: "lg", onClick: handleSpin, disabled: disabled, children: spinning ? l.spinningButton : l.spinButton }) }), alreadyUsed ? (_jsx(Text, { className: "text-center text-sm text-zinc-500 dark:text-zinc-400", children: l.alreadySpun })) : !inWindow ? (_jsx(Text, { className: "text-center text-sm text-zinc-500 dark:text-zinc-400", children: l.outsideWindow })) : null] }));
73
78
  }
@@ -30,6 +30,7 @@ export interface EventDocument {
30
30
  raffleTopN?: number;
31
31
  rafflePrize?: string;
32
32
  rafflePrizeCouponId?: string;
33
+ rafflePrizeProductIds?: string[];
33
34
  raffleGithubFunctionUrl?: string;
34
35
  raffleWinnerUserId?: string;
35
36
  raffleWinnerDisplayName?: string;
@@ -85,6 +85,7 @@ export interface EventItem {
85
85
  raffleTopN?: number;
86
86
  rafflePrize?: string;
87
87
  rafflePrizeCouponId?: string;
88
+ rafflePrizeProductIds?: string[];
88
89
  raffleGithubFunctionUrl?: string;
89
90
  raffleWinnerUserId?: string;
90
91
  raffleWinnerDisplayName?: string;
@@ -1,5 +1,7 @@
1
+ import { sieveFilter, SIEVE_OP } from "@mohasinac/appkit";
1
2
  import { z } from "zod";
2
3
  import { serverLogger } from "../../../monitoring";
4
+ import { sortBy } from "../../../constants/sort";
3
5
  import { faqsRepository } from "../repository/faqs.repository";
4
6
  // --- Schemas --------------------------------------------------------------
5
7
  const faqBaseSchema = z.object({
@@ -89,10 +91,10 @@ export async function listFaqs(params) {
89
91
  export async function listPublicFaqs(category, limit = 20) {
90
92
  const filters = ["isActive==true"];
91
93
  if (category)
92
- filters.push(`category==${category}`);
94
+ filters.push(sieveFilter("category", SIEVE_OP.EQ, category));
93
95
  const result = await faqsRepository.list({
94
96
  filters: filters.join(","),
95
- sorts: "-priority,order",
97
+ sorts: [sortBy("priority", "DESC"), sortBy("order", "ASC")].join(","),
96
98
  page: 1,
97
99
  pageSize: limit,
98
100
  });
@@ -1,7 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Card, Div, Heading, Span, Text, TextLink } from "../../../ui";
3
+ const __P = {
4
+ p8: "p-8",
5
+ };
3
6
  const CLS_CONTACT_CARD = "flex items-center gap-3 rounded-lg border border-zinc-100 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-800 px-4 py-3 hover:border-primary/40 transition-colors";
4
7
  const CLS_CONTACT_LABEL = "text-xs text-zinc-500 dark:text-zinc-400";
5
8
  export function ContactCTA({ email, phone, contactHref, labels, }) {
6
- return (_jsxs(Card, { variant: "outlined", padding: "lg", className: "text-center dark:bg-slate-800/60", children: [_jsx(Div, { className: "mb-6 flex justify-center", children: _jsx(Div, { className: "rounded-full bg-primary/10 p-8", children: _jsx("svg", { className: "h-12 w-12 text-primary", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" }) }) }) }), _jsx(Heading, { level: 2, className: "mb-3 text-2xl font-semibold", children: labels?.title ?? "Need More Help?" }), _jsx(Text, { className: "mx-auto mb-6 max-w-2xl text-zinc-600 dark:text-zinc-300", children: labels?.description ?? "Our support team is here to help you." }), _jsxs(Div, { className: "mb-8 grid grid-cols-1 gap-4 md:grid-cols-3", children: [_jsxs(TextLink, { href: `mailto:${email}`, variant: "none", className: CLS_CONTACT_CARD, children: [_jsx(Text, { className: CLS_CONTACT_LABEL, children: labels?.emailUs ?? "Email Us" }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: email })] }), _jsxs(TextLink, { href: `tel:${phone}`, variant: "none", className: CLS_CONTACT_CARD, children: [_jsx(Text, { className: CLS_CONTACT_LABEL, children: labels?.callUs ?? "Call Us" }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: phone })] }), _jsxs(TextLink, { href: contactHref, className: CLS_CONTACT_CARD, children: [_jsx(Text, { className: CLS_CONTACT_LABEL, children: labels?.contactForm ?? "Contact Form" }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: labels?.submitRequest ?? "Submit a request" })] })] }), _jsxs(TextLink, { href: contactHref, className: "inline-flex items-center gap-2 rounded-xl bg-primary p-6 font-medium text-white transition-colors hover:bg-primary/90", children: [_jsx(Span, { children: labels?.contactTeam ?? "Contact Team" }), _jsx("svg", { className: "h-5 w-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) })] })] }));
9
+ return (_jsxs(Card, { variant: "outlined", padding: "lg", className: "text-center dark:bg-slate-800/60", children: [_jsx(Div, { className: "mb-6 flex justify-center", children: _jsx(Div, { className: `rounded-full bg-primary/10 ${__P.p8}`, children: _jsx("svg", { className: "h-12 w-12 text-primary", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" }) }) }) }), _jsx(Heading, { level: 2, className: "mb-3 text-2xl font-semibold", children: labels?.title ?? "Need More Help?" }), _jsx(Text, { className: "mx-auto mb-6 max-w-2xl text-zinc-600 dark:text-zinc-300", children: labels?.description ?? "Our support team is here to help you." }), _jsxs(Div, { className: "mb-8 grid grid-cols-1 gap-4 md:grid-cols-3", children: [_jsxs(TextLink, { href: `mailto:${email}`, variant: "none", className: CLS_CONTACT_CARD, children: [_jsx(Text, { className: CLS_CONTACT_LABEL, children: labels?.emailUs ?? "Email Us" }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: email })] }), _jsxs(TextLink, { href: `tel:${phone}`, variant: "none", className: CLS_CONTACT_CARD, children: [_jsx(Text, { className: CLS_CONTACT_LABEL, children: labels?.callUs ?? "Call Us" }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: phone })] }), _jsxs(TextLink, { href: contactHref, className: CLS_CONTACT_CARD, children: [_jsx(Text, { className: CLS_CONTACT_LABEL, children: labels?.contactForm ?? "Contact Form" }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: labels?.submitRequest ?? "Submit a request" })] })] }), _jsxs(TextLink, { href: contactHref, className: "inline-flex items-center gap-2 rounded-xl bg-primary p-6 font-medium text-white transition-colors hover:bg-primary/90", children: [_jsx(Span, { children: labels?.contactTeam ?? "Contact Team" }), _jsx("svg", { className: "h-5 w-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) })] })] }));
7
10
  }
@@ -4,11 +4,11 @@ export function FAQCategorySidebar({ selectedCategory, onCategorySelect, categor
4
4
  const totalCount = Object.values(categoryCounts).reduce((sum, count) => sum + count, 0);
5
5
  return (_jsxs(Card, { variant: "outlined", padding: "lg", className: "dark:bg-slate-800/60", children: [_jsx(Heading, { level: 2, className: "mb-6 text-lg font-semibold", children: labels?.title ?? "Categories" }), _jsx(TextLink, { href: allFaqsHref, onClick: () => onCategorySelect?.("all"), className: `mb-3 block w-full rounded-lg p-4 text-left transition-colors ${selectedCategory === "all"
6
6
  ? "bg-primary/10 text-zinc-900 dark:text-zinc-100"
7
- : "text-zinc-600 hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-slate-700"}`, children: _jsxs(Row, { justify: "between", children: [_jsxs(Row, { className: "gap-3", children: [_jsx(Span, { className: "text-2xl", children: "FAQ" }), _jsx(Span, { className: "text-sm font-medium", children: labels?.allFaqs ?? "All FAQs" })] }), _jsx(Span, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: totalCount })] }) }), _jsx(Div, { className: "mt-4 border-t border-zinc-200 pt-4 dark:border-slate-700", children: categories.map((category) => {
7
+ : "text-zinc-600 hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-slate-700"}`, children: _jsxs(Row, { justify: "between", children: [_jsxs(Row, { className: "gap-3", children: [_jsx(Span, { className: "text-2xl", children: "FAQ" }), _jsx(Span, { size: "sm", weight: "medium", children: labels?.allFaqs ?? "All FAQs" })] }), _jsx(Span, { size: "xs", className: "text-zinc-500 dark:text-zinc-400", children: totalCount })] }) }), _jsx(Div, { className: "mt-4 border-t border-zinc-200 pt-4 dark:border-slate-700", children: categories.map((category) => {
8
8
  const isSelected = selectedCategory === category.key;
9
9
  const count = categoryCounts[category.key] || 0;
10
10
  return (_jsxs(TextLink, { href: categoryHref(category.key), onClick: () => onCategorySelect?.(category.key), className: `mb-3 block w-full rounded-lg p-4 text-left transition-colors ${isSelected
11
11
  ? "bg-primary/10 text-zinc-900 dark:text-zinc-100"
12
- : "text-zinc-600 hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-slate-700"}`, children: [_jsxs(Row, { justify: "between", className: "mb-1", children: [_jsxs(Row, { className: "gap-3", children: [category.icon ? (_jsx(Span, { className: "text-2xl", children: category.icon })) : null, _jsx(Span, { className: "text-sm", children: category.label })] }), _jsx(Span, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: count })] }), isSelected && category.description ? (_jsx(Text, { className: "ml-11 text-xs text-zinc-500 dark:text-zinc-400", children: category.description })) : null] }, category.key));
12
+ : "text-zinc-600 hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-slate-700"}`, children: [_jsxs(Row, { justify: "between", className: "mb-1", children: [_jsxs(Row, { className: "gap-3", children: [category.icon ? (_jsx(Span, { className: "text-2xl", children: category.icon })) : null, _jsx(Span, { size: "sm", children: category.label })] }), _jsx(Span, { size: "xs", className: "text-zinc-500 dark:text-zinc-400", children: count })] }), isSelected && category.description ? (_jsx(Text, { className: "ml-11 text-xs text-zinc-500 dark:text-zinc-400", children: category.description })) : null] }, category.key));
13
13
  }) }), contactHref ? (_jsxs(Div, { className: "border-t border-zinc-200 pt-6 dark:border-slate-700", children: [_jsx(Text, { className: "mb-3 text-sm text-zinc-600 dark:text-zinc-300", children: labels?.stillHaveQuestions ?? "Still have questions?" }), _jsx(TextLink, { href: contactHref, className: "block rounded-lg bg-primary p-4 text-center font-medium text-white transition-colors hover:bg-primary/90", children: labels?.contactSupport ?? "Contact Support" })] })) : null] }));
14
14
  }
@@ -1,7 +1,10 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState } from "react";
4
- import { Button, Span, Text } from "../../../ui";
4
+ import { Button, Div, Span, Text } from "../../../ui";
5
+ const __P = {
6
+ p6: "p-6",
7
+ };
5
8
  export function FAQHelpfulButtons({ faqId, initialHelpful, initialNotHelpful, onVote, labels, onVoteError, }) {
6
9
  const [helpful, setHelpful] = useState(initialHelpful);
7
10
  const [notHelpful, setNotHelpful] = useState(initialNotHelpful);
@@ -32,15 +35,15 @@ export function FAQHelpfulButtons({ faqId, initialHelpful, initialNotHelpful, on
32
35
  setIsPending(false);
33
36
  }
34
37
  };
35
- return (_jsxs("div", { className: "rounded-lg bg-zinc-100 p-6 dark:bg-slate-700", "data-section": "faqhelpfulbuttons-div-285", children: [_jsx(Text, { className: "mb-3 text-sm text-zinc-600 dark:text-zinc-300", children: userVote
38
+ return (_jsxs(Div, { className: `rounded-lg bg-zinc-100 ${__P.p6} dark:bg-slate-700`, children: [_jsx(Text, { className: "mb-3 text-sm text-zinc-600 dark:text-zinc-300", children: userVote
36
39
  ? (labels?.thanksForFeedback ?? "Thanks for your feedback")
37
- : (labels?.wasThisHelpful ?? "Was this helpful?") }), _jsxs("div", { className: "flex gap-3", "data-section": "faqhelpfulbuttons-div-286", children: [_jsxs(Button, { variant: "ghost", onClick: () => handleVote(true), disabled: isPending || userVote !== null, className: `flex-1 gap-2 rounded-lg p-4 transition-all ${userVote === "helpful"
40
+ : (labels?.wasThisHelpful ?? "Was this helpful?") }), _jsxs(Div, { className: "flex gap-3", children: [_jsxs(Button, { variant: "ghost", onClick: () => handleVote(true), disabled: isPending || userVote !== null, className: `flex-1 gap-2 rounded-lg p-4 transition-all ${userVote === "helpful"
38
41
  ? "bg-green-600 text-white"
39
42
  : userVote
40
43
  ? "cursor-not-allowed bg-zinc-200 text-zinc-500 opacity-50 dark:bg-slate-600 dark:text-zinc-400"
41
- : "bg-white text-zinc-800 hover:bg-green-50 dark:bg-slate-800 dark:text-zinc-100 dark:hover:bg-green-900/20"}`, children: [_jsx(Span, { className: "text-sm", children: labels?.yes ?? "Yes" }), _jsxs(Span, { className: "text-sm text-zinc-500 dark:text-zinc-400", children: ["(", helpful, ")"] })] }), _jsxs(Button, { variant: "ghost", onClick: () => handleVote(false), disabled: isPending || userVote !== null, className: `flex-1 gap-2 rounded-lg p-4 transition-all ${userVote === "not-helpful"
44
+ : "bg-white text-zinc-800 hover:bg-green-50 dark:bg-slate-800 dark:text-zinc-100 dark:hover:bg-green-900/20"}`, children: [_jsx(Span, { size: "sm", children: labels?.yes ?? "Yes" }), _jsxs(Span, { size: "sm", className: "text-zinc-500 dark:text-zinc-400", children: ["(", helpful, ")"] })] }), _jsxs(Button, { variant: "ghost", onClick: () => handleVote(false), disabled: isPending || userVote !== null, className: `flex-1 gap-2 rounded-lg p-4 transition-all ${userVote === "not-helpful"
42
45
  ? "bg-red-600 text-white"
43
46
  : userVote
44
47
  ? "cursor-not-allowed bg-zinc-200 text-zinc-500 opacity-50 dark:bg-slate-600 dark:text-zinc-400"
45
- : "bg-white text-zinc-800 hover:bg-red-50 dark:bg-slate-800 dark:text-zinc-100 dark:hover:bg-red-900/20"}`, children: [_jsx(Span, { className: "text-sm", children: labels?.no ?? "No" }), _jsxs(Span, { className: "text-sm text-zinc-500 dark:text-zinc-400", children: ["(", notHelpful, ")"] })] })] })] }));
48
+ : "bg-white text-zinc-800 hover:bg-red-50 dark:bg-slate-800 dark:text-zinc-100 dark:hover:bg-red-900/20"}`, children: [_jsx(Span, { size: "sm", children: labels?.no ?? "No" }), _jsxs(Span, { size: "sm", className: "text-zinc-500 dark:text-zinc-400", children: ["(", notHelpful, ")"] })] })] })] }));
46
49
  }
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { Heading, Input, SlottedListingView, Text } from "../../../ui";
3
+ import { Div, Heading, Input, SlottedListingView, Text } from "../../../ui";
4
+ import { sortBy } from "../../../constants/sort";
4
5
  import { FAQCategorySidebar } from "./FAQCategorySidebar";
5
6
  import { FAQSortDropdown } from "./FAQSortDropdown";
6
7
  import { FAQAccordion } from "./FAQAccordion";
@@ -22,7 +23,7 @@ export function FAQPageContent({ initialCategory = "all", categories, routeHelpe
22
23
  });
23
24
  const { faqs: allMatchingFaqs } = useFaqList({
24
25
  search: searchValue.trim() || undefined,
25
- sorts: "-priority,order",
26
+ sorts: [sortBy("priority", "DESC"), sortBy("order", "ASC")].join(","),
26
27
  page: 1,
27
28
  pageSize: 200,
28
29
  });
@@ -38,24 +39,24 @@ export function FAQPageContent({ initialCategory = "all", categories, routeHelpe
38
39
  const handleCategorySelect = (category) => {
39
40
  routeHelpers.navigateToCategory(category);
40
41
  };
41
- return (_jsxs("div", { className: "py-12", "data-section": "faqpagecontent-div-287", children: [_jsxs("div", { className: "mb-12 text-center", "data-section": "faqpagecontent-div-288", children: [_jsx(Heading, { level: 1, className: "mb-4 text-3xl font-bold sm:text-4xl", children: labels.title }), _jsx(Text, { className: "mx-auto max-w-2xl text-zinc-600 dark:text-zinc-300", children: labels.subtitle })] }), _jsx("div", { className: "mb-8 lg:hidden", "data-section": "faqpagecontent-div-289", children: renderMobileCategoryTabs({
42
+ return (_jsxs(Div, { className: "py-12", children: [_jsxs(Div, { className: "mb-12 text-center", children: [_jsx(Heading, { level: 1, className: "mb-4 text-3xl font-bold sm:text-4xl", children: labels.title }), _jsx(Text, { className: "mx-auto max-w-2xl text-zinc-600 dark:text-zinc-300", children: labels.subtitle })] }), _jsx(Div, { className: "mb-8 lg:hidden", children: renderMobileCategoryTabs({
42
43
  selectedCategory,
43
44
  total,
44
45
  categoryCounts,
45
46
  onSelect: handleCategorySelect,
46
- }) }), _jsxs("div", { className: "grid grid-cols-1 gap-8 lg:grid-cols-12", "data-section": "faqpagecontent-div-290", children: [_jsx("div", { className: "hidden lg:col-span-4 lg:block xl:col-span-3", "data-section": "faqpagecontent-div-291", children: _jsx(FAQCategorySidebar, { selectedCategory: selectedCategory, onCategorySelect: handleCategorySelect, categoryCounts: categoryCounts, categories: categories, allFaqsHref: routeHelpers.allFaqsHref, categoryHref: routeHelpers.faqCategoryHref, contactHref: routeHelpers.contactHref, labels: {
47
+ }) }), _jsxs(Div, { className: "grid grid-cols-1 gap-8 lg:grid-cols-12", children: [_jsx(Div, { className: "hidden lg:col-span-4 lg:block xl:col-span-3", children: _jsx(FAQCategorySidebar, { selectedCategory: selectedCategory, onCategorySelect: handleCategorySelect, categoryCounts: categoryCounts, categories: categories, allFaqsHref: routeHelpers.allFaqsHref, categoryHref: routeHelpers.faqCategoryHref, contactHref: routeHelpers.contactHref, labels: {
47
48
  title: labels.categoriesTitle,
48
49
  allFaqs: labels.allFaqs,
49
50
  stillHaveQuestions: labels.stillHaveQuestions,
50
51
  contactSupport: labels.contactSupport,
51
- } }) }), _jsxs("div", { className: "col-span-1 lg:col-span-8 xl:col-span-9", "data-section": "faqpagecontent-div-292", children: [_jsx(SlottedListingView, { portal: "public", inlineToolbar: true, className: "space-y-6", renderHeader: () => (_jsxs(Text, { className: "text-sm text-zinc-600 dark:text-zinc-300", children: [labels.resultCount(total), selectedCategory !== "all"
52
+ } }) }), _jsxs(Div, { className: "col-span-1 lg:col-span-8 xl:col-span-9", children: [_jsx(SlottedListingView, { portal: "public", inlineToolbar: true, className: "space-y-6", renderHeader: () => (_jsxs(Text, { className: "text-sm text-zinc-600 dark:text-zinc-300", children: [labels.resultCount(total), selectedCategory !== "all"
52
53
  ? ` ${labels.inCategory(categories.find((c) => c.key === selectedCategory)?.label ?? selectedCategory)}`
53
54
  : ""] })), renderSearch: () => (_jsx(Input, { value: searchValue, onChange: (event) => onSearchChange(event.target.value), placeholder: labels.searchPlaceholder })), renderSort: () => (_jsx(FAQSortDropdown, { selectedSort: sortOption, onSortChange: onSortChange, labels: {
54
55
  label: labels.sortLabel,
55
56
  helpful: labels.sortHelpful,
56
57
  newest: labels.sortNewest,
57
58
  alphabetical: labels.sortAlphabetical,
58
- } })), renderTable: () => isLoading ? (_jsx(Text, { className: "text-zinc-500 dark:text-zinc-400", children: labels.loading })) : renderAccordion ? (renderAccordion(faqs)) : (_jsx(FAQAccordion, { faqs: faqs })), renderPagination: () => renderPagination?.(total) ?? null, total: total, isLoading: isLoading }), faqs.length > 0 ? (_jsx("div", { className: "mt-12", "data-section": "faqpagecontent-div-293", children: _jsx(ContactCTA, { email: contact.email, phone: contact.phone, contactHref: routeHelpers.contactHref, labels: {
59
+ } })), renderTable: () => isLoading ? (_jsx(Text, { className: "text-zinc-500 dark:text-zinc-400", children: labels.loading })) : renderAccordion ? (renderAccordion(faqs)) : (_jsx(FAQAccordion, { faqs: faqs })), renderPagination: () => renderPagination?.(total) ?? null, total: total, isLoading: isLoading }), faqs.length > 0 ? (_jsx(Div, { className: "mt-12", children: _jsx(ContactCTA, { email: contact.email, phone: contact.phone, contactHref: routeHelpers.contactHref, labels: {
59
60
  title: labels.contactTitle,
60
61
  description: labels.contactDescription,
61
62
  emailUs: labels.contactEmailUs,
@@ -1,10 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Select, Span } from "../../../ui";
2
+ import { Div, Select, Span } from "../../../ui";
3
3
  export function FAQSortDropdown({ selectedSort, onSortChange, labels, }) {
4
4
  const sortOptions = [
5
5
  { value: "helpful", label: labels?.helpful ?? "Most Helpful" },
6
6
  { value: "newest", label: labels?.newest ?? "Newest" },
7
7
  { value: "alphabetical", label: labels?.alphabetical ?? "Alphabetical" },
8
8
  ];
9
- return (_jsxs("div", { className: "flex items-center gap-3", "data-section": "faqsortdropdown-div-294", children: [_jsx(Span, { className: "text-sm text-zinc-600 dark:text-zinc-400", children: labels?.label ?? "Sort" }), _jsx("div", { className: "min-w-44", "data-section": "faqsortdropdown-div-295", children: _jsx(Select, { value: selectedSort, onValueChange: (value) => onSortChange(value), options: sortOptions }) })] }));
9
+ return (_jsxs(Div, { className: "flex items-center gap-3", children: [_jsx(Span, { size: "sm", className: "text-zinc-600 dark:text-zinc-400", children: labels?.label ?? "Sort" }), _jsx(Div, { className: "min-w-44", children: _jsx(Select, { value: selectedSort, onValueChange: (value) => onSortChange(value), options: sortOptions }) })] }));
10
10
  }
@@ -3,6 +3,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useCallback, useEffect, useRef, useState } from "react";
4
4
  import { Button, Div, Input, Row, Span, Text } from "../../ui";
5
5
  import { cn } from "./filterUtils";
6
+ const CLS_BADGE_COUNT = "inline-flex items-center justify-center w-5 h-5 rounded-full bg-emerald-50 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300 ring-1 ring-emerald-600/20 dark:ring-emerald-400/20";
7
+ const CLS_CLEAR_ICON = "inline-flex items-center justify-center w-5 h-5 p-0 text-zinc-500 dark:text-zinc-400 hover:text-red-600 dark:hover:text-red-400 hover:bg-zinc-100 dark:hover:bg-slate-700 transition-colors rounded-full";
6
8
  /**
7
9
  * AsyncFacetSection — collapsible filter section that loads options from the API
8
10
  * with search + pagination. Replaces static `FilterFacetSection` for large datasets
@@ -58,8 +60,8 @@ export function AsyncFacetSection({ title, selected, onChange, loadOptions, sele
58
60
  const selectedLabels = selected
59
61
  .map((v) => labelMap.current.get(v) ?? v)
60
62
  .slice(0, 3);
61
- return (_jsxs(Div, { className: cn("p-4 border-b border-zinc-200 dark:border-slate-700 last:border-b-0", className), children: [_jsxs(Row, { gap: "xs", children: [_jsxs(Button, { type: "button", onClick: () => setCollapsed((c) => !c), variant: "ghost", size: "sm", className: "flex flex-1 items-center justify-between text-sm font-semibold text-zinc-900 dark:text-zinc-50 py-1 hover:opacity-80 transition-opacity", "aria-expanded": !collapsed, children: [_jsxs(Row, { as: Span, gap: "xs", children: [title, hasValue && (_jsx(Span, { className: "inline-flex items-center justify-center w-5 h-5 text-xs rounded-full bg-emerald-50 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300 ring-1 ring-emerald-600/20 dark:ring-emerald-400/20", children: selected.length }))] }), _jsx("svg", { className: cn("w-4 h-4 text-zinc-500 dark:text-zinc-400 transition-transform duration-200", collapsed ? "" : "rotate-180"), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), onClear && hasValue && (_jsx(Button, { type: "button", onClick: onClear, variant: "ghost", size: "sm", className: "inline-flex items-center justify-center w-5 h-5 p-0 text-zinc-500 dark:text-zinc-400 hover:text-red-600 dark:hover:text-red-400 hover:bg-zinc-100 dark:hover:bg-slate-700 transition-colors rounded-full", "aria-label": "Clear filter", children: _jsx("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }))] }), collapsed && hasValue && (_jsxs(Div, { className: "mt-2 flex flex-wrap gap-1", children: [selectedLabels.map((label) => (_jsx(Span, { className: "inline-flex items-center px-2 py-0.5 rounded-full text-xs bg-zinc-100 dark:bg-slate-700 text-zinc-700 dark:text-zinc-300 border border-zinc-200 dark:border-slate-600", children: label }, label))), selected.length > 3 && (_jsxs(Span, { className: "inline-flex items-center px-2 py-0.5 rounded-full text-xs text-zinc-400 dark:text-zinc-400", children: ["+", selected.length - 3, " more"] }))] })), _jsx(Div, { className: "mt-2", children: _jsx(Input, { type: "search", placeholder: "Search\u2026", value: query, onChange: (e) => handleQueryChange(e.target.value), className: "w-full rounded-md border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 px-2.5 py-1.5 text-xs text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-primary-500/20" }) }), !collapsed && (_jsxs(Div, { className: "mt-3 space-y-1", children: [options.map((opt) => {
63
+ return (_jsxs(Div, { className: cn("p-4 border-b border-zinc-200 dark:border-slate-700 last:border-b-0", className), children: [_jsxs(Row, { gap: "xs", children: [_jsxs(Button, { type: "button", onClick: () => setCollapsed((c) => !c), variant: "ghost", size: "sm", className: "flex flex-1 items-center justify-between text-sm font-semibold text-zinc-900 dark:text-zinc-50 py-1 hover:opacity-80 transition-opacity", "aria-expanded": !collapsed, children: [_jsxs(Row, { as: Span, gap: "xs", children: [title, hasValue && (_jsx(Span, { size: "xs", className: CLS_BADGE_COUNT, children: selected.length }))] }), _jsx("svg", { className: cn("w-4 h-4 text-zinc-500 dark:text-zinc-400 transition-transform duration-200", collapsed ? "" : "rotate-180"), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), onClear && hasValue && (_jsx(Button, { type: "button", onClick: onClear, variant: "ghost", size: "sm", className: CLS_CLEAR_ICON, "aria-label": "Clear filter", children: _jsx("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }))] }), collapsed && hasValue && (_jsxs(Div, { className: "mt-2 flex flex-wrap gap-1", children: [selectedLabels.map((label) => (_jsx(Span, { size: "xs", className: "inline-flex items-center px-2 py-0.5 rounded-full bg-zinc-100 dark:bg-slate-700 text-zinc-700 dark:text-zinc-300 border border-zinc-200 dark:border-slate-600", children: label }, label))), selected.length > 3 && (_jsxs(Span, { size: "xs", className: "inline-flex items-center px-2 py-0.5 rounded-full text-zinc-400 dark:text-zinc-400", children: ["+", selected.length - 3, " more"] }))] })), _jsx(Div, { className: "mt-2", children: _jsx(Input, { type: "search", placeholder: "Search\u2026", value: query, onChange: (e) => handleQueryChange(e.target.value), className: "w-full rounded-md border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 px-2.5 py-1.5 text-xs text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-primary-500/20" }) }), !collapsed && (_jsxs(Div, { className: "mt-3 space-y-1", children: [options.map((opt) => {
62
64
  const isSelected = selected.includes(opt.value);
63
- return (_jsxs(Row, { gap: "2.5", className: "py-1 cursor-pointer group", children: [_jsx("input", { type: selectionMode === "single" ? "radio" : "checkbox", checked: isSelected, onChange: () => toggle(opt.value), "aria-label": opt.label, className: "flex-shrink-0 w-4 h-4 rounded border-zinc-300 dark:border-slate-600 cursor-pointer text-primary-600 dark:text-secondary-500" }), _jsx(Span, { className: "flex-1 text-sm text-zinc-700 dark:text-zinc-300 group-hover:text-zinc-900 dark:group-hover:text-zinc-100 transition-colors truncate", children: opt.label }), opt.count !== undefined && (_jsx(Span, { className: "text-xs text-zinc-400 dark:text-zinc-400 tabular-nums flex-shrink-0", children: opt.count }))] }, opt.value));
65
+ return (_jsxs(Row, { gap: "2.5", className: "py-1 cursor-pointer group", children: [_jsx("input", { type: selectionMode === "single" ? "radio" : "checkbox", checked: isSelected, onChange: () => toggle(opt.value), "aria-label": opt.label, className: "flex-shrink-0 w-4 h-4 rounded border-zinc-300 dark:border-slate-600 cursor-pointer text-primary-600 dark:text-secondary-500" }), _jsx(Span, { size: "sm", className: "flex-1 text-zinc-700 dark:text-zinc-300 group-hover:text-zinc-900 dark:group-hover:text-zinc-100 transition-colors truncate", children: opt.label }), opt.count !== undefined && (_jsx(Span, { size: "xs", className: "text-zinc-400 dark:text-zinc-400 tabular-nums flex-shrink-0", children: opt.count }))] }, opt.value));
64
66
  }), options.length === 0 && !loading && (_jsx(Text, { className: "text-xs text-zinc-400 dark:text-zinc-400 py-1", children: "No results" })), loading && (_jsx(Text, { className: "text-xs text-zinc-400 dark:text-zinc-400 py-1 animate-pulse", children: "Loading\u2026" })), hasMore && !loading && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "w-full text-xs text-left text-zinc-400 dark:text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300 py-1", onClick: () => void load(query, page + 1), children: "Load more\u2026" }))] }))] }));
65
67
  }
@@ -3,6 +3,14 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useRef, useState } from "react";
4
4
  import { Button, Div, Input, Row, Span, Text } from "../../ui";
5
5
  import { cn } from "./filterUtils";
6
+ const __O = {
7
+ yAuto: "overflow-y-auto",
8
+ };
9
+ const CLS_OPTION_SELECTED = "border-emerald-500 bg-emerald-50 text-emerald-700 dark:border-emerald-500/60 dark:bg-emerald-900/20 dark:text-emerald-300";
10
+ const CLS_OPTION_DOT = "inline-flex h-4 w-4 items-center justify-center rounded-full bg-emerald-600 text-[10px] text-white";
11
+ const CLS_CLEAR_BTN = "w-full py-1 text-xs text-zinc-400 transition-colors hover:text-red-600";
12
+ const CLS_BADGE_COUNT = "inline-flex items-center justify-center w-5 h-5 rounded-full bg-emerald-50 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300 ring-1 ring-emerald-600/20 dark:ring-emerald-400/20";
13
+ const CLS_CLEAR_ICON = "inline-flex items-center justify-center w-5 h-5 p-0 text-zinc-500 dark:text-zinc-400 hover:text-red-600 dark:hover:text-red-400 hover:bg-zinc-100 dark:hover:bg-slate-700 transition-colors rounded-full";
6
14
  /**
7
15
  * FilterFacetSection — collapsible checkbox/radio filter section.
8
16
  * Supports single-select and multi-select modes.
@@ -60,15 +68,15 @@ export function FilterFacetSection({ title, options, selected, onChange, selecti
60
68
  // ── Dropdown variant ────────────────────────────────────────────────────
61
69
  if (displayAs === "dropdown") {
62
70
  return (_jsxs(Div, { ref: dropdownRef, className: cn("relative inline-block", className), children: [_jsxs(Button, { type: "button", onClick: () => setDropdownOpen((o) => !o), variant: "ghost", className: cn("inline-flex items-center gap-1.5 rounded-full border px-3 py-1.5 text-sm font-medium transition-colors", hasValue
63
- ? "border-emerald-500 bg-emerald-50 text-emerald-700 dark:border-emerald-500/60 dark:bg-emerald-900/20 dark:text-emerald-300"
64
- : "border-zinc-200 bg-white text-zinc-700 hover:border-zinc-400 dark:border-slate-700 dark:bg-slate-900 dark:text-zinc-200 dark:hover:border-slate-500"), children: [title, hasValue && (_jsx(Span, { className: "inline-flex h-4 w-4 items-center justify-center rounded-full bg-emerald-600 text-[10px] font-bold text-white", children: selected.length })), _jsx("svg", { className: cn("h-3.5 w-3.5 text-zinc-400 transition-transform", dropdownOpen ? "rotate-180" : ""), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), dropdownOpen && (_jsxs(Div, { className: "absolute left-0 top-full z-[var(--appkit-z-dropdown,50)] mt-1 min-w-[180px] max-w-[260px] rounded-xl border border-zinc-200 bg-white shadow-lg dark:border-slate-700 dark:bg-slate-900", children: [searchable && (_jsx(Div, { className: "border-b border-zinc-100 p-2 dark:border-slate-800", children: _jsx(Input, { type: "search", placeholder: "Search\u2026", value: search, onChange: (e) => handleSearch(e.target.value), className: "w-full rounded-md border border-zinc-200 bg-white px-2 py-1 text-xs text-zinc-900 focus:outline-none dark:border-slate-700 dark:bg-slate-800/60 dark:text-zinc-100" }) })), _jsxs(Div, { className: "max-h-56 overflow-y-auto py-1", children: [filtered.map((option) => {
71
+ ? CLS_OPTION_SELECTED
72
+ : "border-zinc-200 bg-white text-zinc-700 hover:border-zinc-400 dark:border-slate-700 dark:bg-slate-900 dark:text-zinc-200 dark:hover:border-slate-500"), children: [title, hasValue && (_jsx(Span, { weight: "bold", className: CLS_OPTION_DOT, children: selected.length })), _jsx("svg", { className: cn("h-3.5 w-3.5 text-zinc-400 transition-transform", dropdownOpen ? "rotate-180" : ""), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), dropdownOpen && (_jsxs(Div, { className: "absolute left-0 top-full z-[var(--appkit-z-dropdown,50)] mt-1 min-w-[180px] max-w-[260px] rounded-xl border border-zinc-200 bg-white shadow-lg dark:border-slate-700 dark:bg-slate-900", children: [searchable && (_jsx(Div, { className: "border-b border-zinc-100 p-2 dark:border-slate-800", children: _jsx(Input, { type: "search", placeholder: "Search\u2026", value: search, onChange: (e) => handleSearch(e.target.value), className: "w-full rounded-md border border-zinc-200 bg-white px-2 py-1 text-xs text-zinc-900 focus:outline-none dark:border-slate-700 dark:bg-slate-800/60 dark:text-zinc-100" }) })), _jsxs(Div, { className: `max-h-56 ${__O.yAuto} py-1`, children: [filtered.map((option) => {
65
73
  const isSelected = selected.includes(option.value);
66
- return (_jsxs(Row, { gap: "xs", className: "cursor-pointer rounded-lg px-3 py-1.5 hover:bg-zinc-50 dark:hover:bg-slate-800 mx-1", onClick: () => toggle(option.value), children: [_jsx("input", { type: selectionMode === "single" ? "radio" : "checkbox", checked: isSelected, onChange: () => toggle(option.value), "aria-label": option.label, className: "h-3.5 w-3.5 flex-shrink-0 cursor-pointer rounded border-zinc-300 text-primary-600 dark:border-slate-600 dark:text-secondary-500" }), _jsx(Span, { className: "flex-1 truncate text-xs text-zinc-700 dark:text-zinc-300", children: option.label }), option.count !== undefined && (_jsx(Span, { className: "flex-shrink-0 text-[10px] tabular-nums text-zinc-400 dark:text-zinc-400", children: option.count }))] }, option.value));
67
- }), filtered.length === 0 && (_jsx(Text, { className: "px-3 py-2 text-xs text-zinc-400 dark:text-zinc-400", children: "No results" }))] }), hasValue && (_jsx(Div, { className: "border-t border-zinc-100 p-1 dark:border-slate-800", children: _jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "w-full py-1 text-xs text-zinc-400 transition-colors hover:text-red-600", onClick: () => { onChange([]); onClear?.(); setDropdownOpen(false); }, children: "Clear" }) }))] }))] }));
74
+ return (_jsxs(Row, { gap: "xs", className: "cursor-pointer rounded-lg px-3 py-1.5 hover:bg-zinc-50 dark:hover:bg-slate-800 mx-1", onClick: () => toggle(option.value), children: [_jsx("input", { type: selectionMode === "single" ? "radio" : "checkbox", checked: isSelected, onChange: () => toggle(option.value), "aria-label": option.label, className: "h-3.5 w-3.5 flex-shrink-0 cursor-pointer rounded border-zinc-300 text-primary-600 dark:border-slate-600 dark:text-secondary-500" }), _jsx(Span, { size: "xs", className: "flex-1 truncate text-zinc-700 dark:text-zinc-300", children: option.label }), option.count !== undefined && (_jsx(Span, { className: "flex-shrink-0 text-[10px] tabular-nums text-zinc-400 dark:text-zinc-400", children: option.count }))] }, option.value));
75
+ }), filtered.length === 0 && (_jsx(Text, { className: "px-3 py-2 text-xs text-zinc-400 dark:text-zinc-400", children: "No results" }))] }), hasValue && (_jsx(Div, { className: "border-t border-zinc-100 p-1 dark:border-slate-800", children: _jsx(Button, { type: "button", variant: "ghost", size: "sm", className: CLS_CLEAR_BTN, onClick: () => { onChange([]); onClear?.(); setDropdownOpen(false); }, children: "Clear" }) }))] }))] }));
68
76
  }
69
77
  // ── Accordion variant (default) ─────────────────────────────────────────
70
- return (_jsxs(Div, { className: cn("p-4 border-b border-zinc-200 dark:border-slate-700 last:border-b-0", className), children: [_jsxs(Row, { gap: "xs", children: [_jsxs(Button, { type: "button", onClick: handleToggle, variant: "ghost", size: "sm", className: "flex flex-1 items-center justify-between text-sm font-semibold text-zinc-900 dark:text-zinc-50 py-1 hover:opacity-80 transition-opacity", "aria-expanded": !isCollapsed, children: [_jsxs(Row, { as: Span, gap: "xs", children: [title, hasValue && (_jsx(Span, { className: "inline-flex items-center justify-center w-5 h-5 text-xs rounded-full bg-emerald-50 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300 ring-1 ring-emerald-600/20 dark:ring-emerald-400/20", children: selected.length }))] }), _jsx("svg", { className: cn("w-4 h-4 text-zinc-500 dark:text-zinc-400 transition-transform duration-200", isCollapsed ? "" : "rotate-180"), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), onClear && hasValue && (_jsx(Button, { type: "button", onClick: onClear, variant: "ghost", size: "sm", className: "inline-flex items-center justify-center w-5 h-5 p-0 text-zinc-500 dark:text-zinc-400 hover:text-red-600 dark:hover:text-red-400 hover:bg-zinc-100 dark:hover:bg-slate-700 transition-colors rounded-full", "aria-label": "Clear filter", children: _jsx("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }))] }), isCollapsed && hasValue && (_jsxs(Div, { className: "mt-2 flex flex-wrap gap-1", children: [selectedLabels.map((label) => (_jsx(Span, { className: "inline-flex items-center px-2 py-0.5 rounded-full text-xs bg-zinc-100 dark:bg-slate-700 text-zinc-700 dark:text-zinc-300 border border-zinc-200 dark:border-slate-600", children: label }, label))), selected.length > 3 && (_jsxs(Span, { className: "inline-flex items-center px-2 py-0.5 rounded-full text-xs text-zinc-400 dark:text-zinc-400", children: ["+", selected.length - 3, " more"] }))] })), searchable && (_jsx(Div, { className: "mt-2", children: _jsx(Input, { type: "search", placeholder: "Search\u2026", value: search, onChange: (e) => handleSearch(e.target.value), className: "w-full rounded-md border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 px-2.5 py-1.5 text-xs text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-primary-500/20 dark:focus:ring-secondary-400/20" }) })), !isCollapsed && (_jsxs(Div, { className: "mt-3 space-y-1", children: [filtered.map((option) => {
78
+ return (_jsxs(Div, { className: cn("p-4 border-b border-zinc-200 dark:border-slate-700 last:border-b-0", className), children: [_jsxs(Row, { gap: "xs", children: [_jsxs(Button, { type: "button", onClick: handleToggle, variant: "ghost", size: "sm", className: "flex flex-1 items-center justify-between text-sm font-semibold text-zinc-900 dark:text-zinc-50 py-1 hover:opacity-80 transition-opacity", "aria-expanded": !isCollapsed, children: [_jsxs(Row, { as: Span, gap: "xs", children: [title, hasValue && (_jsx(Span, { size: "xs", className: CLS_BADGE_COUNT, children: selected.length }))] }), _jsx("svg", { className: cn("w-4 h-4 text-zinc-500 dark:text-zinc-400 transition-transform duration-200", isCollapsed ? "" : "rotate-180"), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), onClear && hasValue && (_jsx(Button, { type: "button", onClick: onClear, variant: "ghost", size: "sm", className: CLS_CLEAR_ICON, "aria-label": "Clear filter", children: _jsx("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }))] }), isCollapsed && hasValue && (_jsxs(Div, { className: "mt-2 flex flex-wrap gap-1", children: [selectedLabels.map((label) => (_jsx(Span, { size: "xs", className: "inline-flex items-center px-2 py-0.5 rounded-full bg-zinc-100 dark:bg-slate-700 text-zinc-700 dark:text-zinc-300 border border-zinc-200 dark:border-slate-600", children: label }, label))), selected.length > 3 && (_jsxs(Span, { size: "xs", className: "inline-flex items-center px-2 py-0.5 rounded-full text-zinc-400 dark:text-zinc-400", children: ["+", selected.length - 3, " more"] }))] })), searchable && (_jsx(Div, { className: "mt-2", children: _jsx(Input, { type: "search", placeholder: "Search\u2026", value: search, onChange: (e) => handleSearch(e.target.value), className: "w-full rounded-md border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 px-2.5 py-1.5 text-xs text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-primary-500/20 dark:focus:ring-secondary-400/20" }) })), !isCollapsed && (_jsxs(Div, { className: "mt-3 space-y-1", children: [filtered.map((option) => {
71
79
  const isSelected = selected.includes(option.value);
72
- return (_jsxs(Row, { gap: "2.5", className: "py-1 cursor-pointer group", children: [selectionMode === "single" ? (_jsx("input", { type: "radio", checked: isSelected, onChange: () => toggle(option.value), "aria-label": option.label, className: cn("flex-shrink-0 border-zinc-300 dark:border-slate-600 cursor-pointer", "w-4 h-4 rounded-full text-primary-600 dark:text-secondary-500", "focus:ring-primary-500/30 dark:focus:ring-secondary-400/30") })) : (_jsx("input", { type: "checkbox", checked: isSelected, onChange: () => toggle(option.value), "aria-label": option.label, className: cn("flex-shrink-0 border-zinc-300 dark:border-slate-600 cursor-pointer", "w-4 h-4 rounded text-primary-600 dark:text-secondary-500 checked:bg-primary-600 dark:checked:bg-secondary-500", "focus:ring-primary-500/30 dark:focus:ring-secondary-400/30") })), _jsx(Span, { className: "flex-1 text-sm text-zinc-700 dark:text-zinc-300 group-hover:text-zinc-900 dark:group-hover:text-zinc-100 transition-colors truncate", children: option.label }), option.count !== undefined && (_jsx(Span, { className: "text-xs text-zinc-400 dark:text-zinc-400 tabular-nums flex-shrink-0", children: option.count }))] }, option.value));
80
+ return (_jsxs(Row, { gap: "2.5", className: "py-1 cursor-pointer group", children: [selectionMode === "single" ? (_jsx("input", { type: "radio", checked: isSelected, onChange: () => toggle(option.value), "aria-label": option.label, className: cn("flex-shrink-0 border-zinc-300 dark:border-slate-600 cursor-pointer", "w-4 h-4 rounded-full text-primary-600 dark:text-secondary-500", "focus:ring-primary-500/30 dark:focus:ring-secondary-400/30") })) : (_jsx("input", { type: "checkbox", checked: isSelected, onChange: () => toggle(option.value), "aria-label": option.label, className: cn("flex-shrink-0 border-zinc-300 dark:border-slate-600 cursor-pointer", "w-4 h-4 rounded text-primary-600 dark:text-secondary-500 checked:bg-primary-600 dark:checked:bg-secondary-500", "focus:ring-primary-500/30 dark:focus:ring-secondary-400/30") })), _jsx(Span, { size: "sm", className: "flex-1 text-zinc-700 dark:text-zinc-300 group-hover:text-zinc-900 dark:group-hover:text-zinc-100 transition-colors truncate", children: option.label }), option.count !== undefined && (_jsx(Span, { size: "xs", className: "text-zinc-400 dark:text-zinc-400 tabular-nums flex-shrink-0", children: option.count }))] }, option.value));
73
81
  }), filtered.length === 0 && (_jsx(Text, { className: "text-xs text-zinc-400 dark:text-zinc-400 py-1", children: "No results" }))] }))] }));
74
82
  }
@@ -3,10 +3,12 @@ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
3
3
  import { useState } from "react";
4
4
  import { Button, Div, Input, Slider, Span, Stack, Text } from "../../ui";
5
5
  import { cn } from "./filterUtils";
6
+ const CLS_BADGE_COUNT = "inline-flex items-center justify-center w-5 h-5 rounded-full bg-emerald-50 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300 ring-1 ring-emerald-600/20";
7
+ const CLS_CLEAR_BTN = "inline-flex items-center justify-center w-5 h-5 text-zinc-500 dark:text-zinc-400 hover:text-red-600 dark:hover:text-red-400 rounded-full transition-colors";
6
8
  function DualSlider({ minValue, maxValue, onMinChange, onMaxChange, minBound, maxBound, step = 1, prefix = "", }) {
7
9
  const minNum = Math.max(minBound, Math.min(parseFloat(minValue) || minBound, maxBound));
8
10
  const maxNum = Math.min(maxBound, Math.max(parseFloat(maxValue) || maxBound, minBound));
9
- return (_jsxs(Stack, { gap: "sm", className: "w-full", children: [_jsxs(Div, { className: "flex items-center justify-between", children: [_jsxs(Span, { className: "text-sm font-semibold tabular-nums text-primary-600 dark:text-secondary-400", children: [prefix, minNum] }), _jsx(Span, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "-" }), _jsxs(Span, { className: "text-sm font-semibold tabular-nums text-primary-600 dark:text-secondary-400", children: [prefix, maxNum] })] }), _jsxs(Stack, { gap: "xs", "aria-hidden": "true", children: [_jsx(Slider, { value: minNum, min: minBound, max: Math.max(minBound, maxNum - step), step: step, onChange: (v) => onMinChange(String(v)) }), _jsx(Slider, { value: maxNum, min: Math.min(maxBound, minNum + step), max: maxBound, step: step, onChange: (v) => onMaxChange(String(v)) })] }), _jsxs(Div, { className: "flex items-center justify-between", children: [_jsxs(Span, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: [prefix, minBound] }), _jsxs(Span, { className: "text-xs text-zinc-500 dark:text-zinc-400", children: [prefix, maxBound] })] })] }));
11
+ return (_jsxs(Stack, { gap: "sm", className: "w-full", children: [_jsxs(Div, { className: "flex items-center justify-between", children: [_jsxs(Span, { size: "sm", weight: "semibold", className: "tabular-nums text-primary-600 dark:text-secondary-400", children: [prefix, minNum] }), _jsx(Span, { size: "xs", className: "text-zinc-500 dark:text-zinc-400", children: "-" }), _jsxs(Span, { size: "sm", weight: "semibold", className: "tabular-nums text-primary-600 dark:text-secondary-400", children: [prefix, maxNum] })] }), _jsxs(Stack, { gap: "xs", "aria-hidden": "true", children: [_jsx(Slider, { value: minNum, min: minBound, max: Math.max(minBound, maxNum - step), step: step, onChange: (v) => onMinChange(String(v)) }), _jsx(Slider, { value: maxNum, min: Math.min(maxBound, minNum + step), max: maxBound, step: step, onChange: (v) => onMaxChange(String(v)) })] }), _jsxs(Div, { className: "flex items-center justify-between", children: [_jsxs(Span, { size: "xs", className: "text-zinc-500 dark:text-zinc-400", children: [prefix, minBound] }), _jsxs(Span, { size: "xs", className: "text-zinc-500 dark:text-zinc-400", children: [prefix, maxBound] })] })] }));
10
12
  }
11
13
  export function RangeFilter({ title, minLabel, maxLabel, minValue, maxValue, onMinChange, onMaxChange, type = "number", prefix, minPlaceholder, maxPlaceholder, defaultCollapsed = true, showSlider = false, minBound, maxBound, step = 1, className = "", isOpen: controlledOpen, onToggle, onClear, }) {
12
14
  const isControlled = controlledOpen !== undefined;
@@ -24,5 +26,5 @@ export function RangeFilter({ title, minLabel, maxLabel, minValue, maxValue, onM
24
26
  maxBound !== undefined;
25
27
  const hasValue = !!(minValue || maxValue);
26
28
  const inputClass = "w-full rounded-md border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 px-2.5 py-1.5 text-xs text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-primary-500/20 dark:focus:ring-secondary-400/20";
27
- return (_jsxs(Div, { role: "group", "aria-labelledby": `rf-${title}`, className: cn("p-4 border-b border-zinc-200 dark:border-slate-700 last:border-b-0", className), children: [_jsxs(Div, { className: "flex items-center gap-2", children: [_jsxs(Button, { type: "button", id: `rf-${title}`, onClick: handleToggle, variant: "ghost", size: "sm", className: "flex flex-1 items-center justify-between text-sm font-semibold text-zinc-900 dark:text-zinc-50 py-1 hover:opacity-80 transition-opacity", "aria-expanded": !isCollapsed, children: [_jsxs(Span, { className: "flex items-center gap-2", children: [title, hasValue && (_jsx(Span, { className: "inline-flex items-center justify-center w-5 h-5 text-xs rounded-full bg-emerald-50 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300 ring-1 ring-emerald-600/20", children: "1" }))] }), _jsx("svg", { className: cn("w-4 h-4 text-zinc-500 dark:text-zinc-400 transition-transform duration-200", isCollapsed ? "" : "rotate-180"), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), onClear && hasValue && (_jsx(Button, { type: "button", onClick: onClear, variant: "ghost", size: "sm", className: "inline-flex items-center justify-center w-5 h-5 text-zinc-500 dark:text-zinc-400 hover:text-red-600 dark:hover:text-red-400 rounded-full transition-colors", "aria-label": "Clear", children: _jsx("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }))] }), !isCollapsed && (_jsxs(Stack, { gap: "3", className: "mt-3", children: [canShowSlider && (_jsx(DualSlider, { minValue: minValue, maxValue: maxValue, onMinChange: onMinChange, onMaxChange: onMaxChange, minBound: minBound, maxBound: maxBound, step: step, prefix: prefix })), _jsxs(Div, { className: "flex items-end gap-2", children: [_jsxs(Div, { className: "flex-1 min-w-0", children: [minLabel && (_jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 mb-1", children: minLabel })), _jsxs(Div, { className: "relative", children: [prefix && (_jsx(Span, { className: "absolute left-2 top-1/2 -translate-y-1/2 text-xs text-zinc-400 dark:text-zinc-400 pointer-events-none", children: prefix })), _jsx(Input, { type: type, value: minValue, onChange: (e) => onMinChange(e.target.value), placeholder: minPlaceholder ?? (type === "date" ? "From" : "Min"), className: cn(inputClass, prefix ? "pl-5" : "") })] })] }), _jsx(Span, { className: "flex-shrink-0 pb-1.5 text-zinc-400 dark:text-zinc-400 text-xs", children: "-" }), _jsxs(Div, { className: "flex-1 min-w-0", children: [maxLabel && (_jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 mb-1", children: maxLabel })), _jsxs(Div, { className: "relative", children: [prefix && (_jsx(Span, { className: "absolute left-2 top-1/2 -translate-y-1/2 text-xs text-zinc-400 dark:text-zinc-400 pointer-events-none", children: prefix })), _jsx(Input, { type: type, value: maxValue, onChange: (e) => onMaxChange(e.target.value), placeholder: maxPlaceholder ?? (type === "date" ? "To" : "Max"), className: cn(inputClass, prefix ? "pl-5" : "") })] })] })] })] }))] }));
29
+ return (_jsxs(Div, { role: "group", "aria-labelledby": `rf-${title}`, className: cn("p-4 border-b border-zinc-200 dark:border-slate-700 last:border-b-0", className), children: [_jsxs(Div, { className: "flex items-center gap-2", children: [_jsxs(Button, { type: "button", id: `rf-${title}`, onClick: handleToggle, variant: "ghost", size: "sm", className: "flex flex-1 items-center justify-between text-sm font-semibold text-zinc-900 dark:text-zinc-50 py-1 hover:opacity-80 transition-opacity", "aria-expanded": !isCollapsed, children: [_jsxs(Span, { className: "flex items-center gap-2", children: [title, hasValue && (_jsx(Span, { size: "xs", className: CLS_BADGE_COUNT, children: "1" }))] }), _jsx("svg", { className: cn("w-4 h-4 text-zinc-500 dark:text-zinc-400 transition-transform duration-200", isCollapsed ? "" : "rotate-180"), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), onClear && hasValue && (_jsx(Button, { type: "button", onClick: onClear, variant: "ghost", size: "sm", className: CLS_CLEAR_BTN, "aria-label": "Clear", children: _jsx("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }))] }), !isCollapsed && (_jsxs(Stack, { gap: "3", className: "mt-3", children: [canShowSlider && (_jsx(DualSlider, { minValue: minValue, maxValue: maxValue, onMinChange: onMinChange, onMaxChange: onMaxChange, minBound: minBound, maxBound: maxBound, step: step, prefix: prefix })), _jsxs(Div, { className: "flex items-end gap-2", children: [_jsxs(Div, { className: "flex-1 min-w-0", children: [minLabel && (_jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 mb-1", children: minLabel })), _jsxs(Div, { className: "relative", children: [prefix && (_jsx(Span, { size: "xs", className: "absolute left-2 top-1/2 -translate-y-1/2 text-zinc-400 dark:text-zinc-400 pointer-events-none", children: prefix })), _jsx(Input, { type: type, value: minValue, onChange: (e) => onMinChange(e.target.value), placeholder: minPlaceholder ?? (type === "date" ? "From" : "Min"), className: cn(inputClass, prefix ? "pl-5" : "") })] })] }), _jsx(Span, { size: "xs", className: "flex-shrink-0 pb-1.5 text-zinc-400 dark:text-zinc-400", children: "-" }), _jsxs(Div, { className: "flex-1 min-w-0", children: [maxLabel && (_jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 mb-1", children: maxLabel })), _jsxs(Div, { className: "relative", children: [prefix && (_jsx(Span, { size: "xs", className: "absolute left-2 top-1/2 -translate-y-1/2 text-zinc-400 dark:text-zinc-400 pointer-events-none", children: prefix })), _jsx(Input, { type: type, value: maxValue, onChange: (e) => onMaxChange(e.target.value), placeholder: maxPlaceholder ?? (type === "date" ? "To" : "Max"), className: cn(inputClass, prefix ? "pl-5" : "") })] })] })] })] }))] }));
28
30
  }
@@ -3,6 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState } from "react";
4
4
  import { Button, Div, Row, Span, Text, Toggle } from "../../ui";
5
5
  import { cn } from "./filterUtils";
6
+ const CLS_CLEAR_BTN = "inline-flex items-center justify-center w-5 h-5 text-zinc-500 dark:text-zinc-400 hover:text-red-600 dark:hover:text-red-400 rounded-full transition-colors";
6
7
  export function SwitchFilter({ title, label, checked, onChange, defaultCollapsed = false, className = "", isOpen: controlledOpen, onToggle, onClear, }) {
7
8
  const isControlled = controlledOpen !== undefined;
8
9
  const [internalCollapsed, setInternalCollapsed] = useState(defaultCollapsed);
@@ -13,5 +14,5 @@ export function SwitchFilter({ title, label, checked, onChange, defaultCollapsed
13
14
  else
14
15
  setInternalCollapsed((c) => !c);
15
16
  };
16
- return (_jsxs(Div, { role: "group", "aria-labelledby": `sf-${title}`, className: cn("p-4 border-b border-zinc-200 dark:border-slate-700 last:border-b-0", className), children: [_jsxs(Row, { className: "gap-2", children: [_jsxs(Button, { type: "button", id: `sf-${title}`, onClick: handleToggle, variant: "ghost", size: "sm", className: "flex flex-1 items-center justify-between text-sm font-semibold text-zinc-900 dark:text-zinc-50 py-1 hover:opacity-80 transition-opacity", "aria-expanded": !isCollapsed, children: [_jsx(Text, { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-50", children: title }), _jsx("svg", { className: cn("w-4 h-4 text-zinc-500 dark:text-zinc-400 transition-transform duration-200", isCollapsed ? "" : "rotate-180"), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), checked && onClear && (_jsx(Button, { type: "button", onClick: onClear, variant: "ghost", size: "sm", className: "inline-flex items-center justify-center w-5 h-5 text-zinc-500 dark:text-zinc-400 hover:text-red-600 dark:hover:text-red-400 rounded-full transition-colors", "aria-label": "Clear", children: _jsx("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }))] }), !isCollapsed && (_jsxs(Div, { className: "mt-3 flex items-center justify-between gap-3", children: [_jsx(Span, { className: "text-sm text-zinc-700 dark:text-zinc-300", children: label }), _jsx(Toggle, { checked: checked, onChange: onChange, size: "sm" })] }))] }));
17
+ return (_jsxs(Div, { role: "group", "aria-labelledby": `sf-${title}`, className: cn("p-4 border-b border-zinc-200 dark:border-slate-700 last:border-b-0", className), children: [_jsxs(Row, { className: "gap-2", children: [_jsxs(Button, { type: "button", id: `sf-${title}`, onClick: handleToggle, variant: "ghost", size: "sm", className: "flex flex-1 items-center justify-between text-sm font-semibold text-zinc-900 dark:text-zinc-50 py-1 hover:opacity-80 transition-opacity", "aria-expanded": !isCollapsed, children: [_jsx(Text, { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-50", children: title }), _jsx("svg", { className: cn("w-4 h-4 text-zinc-500 dark:text-zinc-400 transition-transform duration-200", isCollapsed ? "" : "rotate-180"), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), checked && onClear && (_jsx(Button, { type: "button", onClick: onClear, variant: "ghost", size: "sm", className: CLS_CLEAR_BTN, "aria-label": "Clear", children: _jsx("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }))] }), !isCollapsed && (_jsxs(Div, { className: "mt-3 flex items-center justify-between gap-3", children: [_jsx(Span, { size: "sm", className: "text-zinc-700 dark:text-zinc-300", children: label }), _jsx(Toggle, { checked: checked, onChange: onChange, size: "sm" })] }))] }));
17
18
  }
@@ -12,5 +12,5 @@ export function Checkbox({ label, suffix, error, indeterminate, className = "",
12
12
  }, [indeterminate]);
13
13
  return (_jsxs(Div, { className: "w-full", children: [_jsxs("label", { className: "flex flex-row items-center gap-3 cursor-pointer group", children: [_jsxs(Div, { className: "relative flex items-center justify-center flex-shrink-0", children: [_jsx("input", { ref: inputRef, type: "checkbox", checked: checked, className: cn("peer w-5 h-5 rounded-md border-2 cursor-pointer", "transition-all duration-200 appearance-none", error
14
14
  ? "border-red-400 dark:border-red-500"
15
- : "border-zinc-300 dark:border-slate-600", "checked:bg-primary-600 checked:border-primary-600", "dark:checked:bg-secondary-500 dark:checked:border-secondary-500", "hover:border-primary-400 dark:hover:border-secondary-400", "focus:outline-none focus:ring-2 focus:ring-primary-500/30 focus:ring-offset-1", "dark:focus:ring-secondary-400/30 dark:focus:ring-offset-slate-900", "disabled:opacity-50 disabled:cursor-not-allowed", className), ...props }), _jsx("svg", { className: "absolute w-3 h-3 text-white pointer-events-none opacity-0 peer-checked:opacity-100 transition-opacity duration-150", viewBox: "0 0 12 12", fill: "none", "aria-hidden": "true", children: indeterminate ? (_jsx("line", { x1: "2", y1: "6", x2: "10", y2: "6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })) : (_jsx("path", { d: "M2 6L5 9L10 3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })) })] }), (label || suffix) && (_jsxs(Span, { className: "flex items-center gap-2 text-sm text-zinc-700 dark:text-zinc-300 group-hover:text-zinc-900 dark:group-hover:text-zinc-100 transition-colors", children: [label, suffix] }))] }), error && (_jsx(Text, { className: cn(ERROR_BASE, "mt-1.5"), role: "alert", children: error }))] }));
15
+ : "border-zinc-300 dark:border-slate-600", "checked:bg-primary-600 checked:border-primary-600", "dark:checked:bg-secondary-500 dark:checked:border-secondary-500", "hover:border-primary-400 dark:hover:border-secondary-400", "focus:outline-none focus:ring-2 focus:ring-primary-500/30 focus:ring-offset-1", "dark:focus:ring-secondary-400/30 dark:focus:ring-offset-slate-900", "disabled:opacity-50 disabled:cursor-not-allowed", className), ...props }), _jsx("svg", { className: "absolute w-3 h-3 text-white pointer-events-none opacity-0 peer-checked:opacity-100 transition-opacity duration-150", viewBox: "0 0 12 12", fill: "none", "aria-hidden": "true", children: indeterminate ? (_jsx("line", { x1: "2", y1: "6", x2: "10", y2: "6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })) : (_jsx("path", { d: "M2 6L5 9L10 3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })) })] }), (label || suffix) && (_jsxs(Span, { size: "sm", className: "flex items-center gap-2 text-zinc-700 dark:text-zinc-300 group-hover:text-zinc-900 dark:group-hover:text-zinc-100 transition-colors", children: [label, suffix] }))] }), error && (_jsx(Text, { className: cn(ERROR_BASE, "mt-1.5"), role: "alert", children: error }))] }));
16
16
  }
@@ -5,7 +5,7 @@ export function RadioGroup({ name, options, value, onChange, label, error, orien
5
5
  if (variant === "classic") {
6
6
  return (_jsxs(Div, { className: "w-full", children: [label && _jsx(Text, { className: LABEL_BASE, children: label }), _jsx(Div, { className: cn("flex gap-3", orientation === "vertical" ? "flex-col" : "flex-row flex-wrap"), children: options.map((option) => {
7
7
  const isSelected = value === option.value;
8
- return (_jsxs("label", { className: cn("flex items-center gap-2.5 cursor-pointer", option.disabled && "opacity-50 cursor-not-allowed"), children: [_jsx("input", { type: "radio", name: name, value: option.value, checked: isSelected, disabled: option.disabled, onChange: () => !option.disabled && onChange?.(option.value), className: "w-4 h-4 text-primary-600 dark:text-secondary-500 border-zinc-300 dark:border-slate-600 focus:ring-primary-500/30 dark:focus:ring-secondary-400/30" }), _jsx(Span, { className: "text-sm text-zinc-700 dark:text-zinc-300", children: option.label })] }, option.value));
8
+ return (_jsxs("label", { className: cn("flex items-center gap-2.5 cursor-pointer", option.disabled && "opacity-50 cursor-not-allowed"), children: [_jsx("input", { type: "radio", name: name, value: option.value, checked: isSelected, disabled: option.disabled, onChange: () => !option.disabled && onChange?.(option.value), className: "w-4 h-4 text-primary-600 dark:text-secondary-500 border-zinc-300 dark:border-slate-600 focus:ring-primary-500/30 dark:focus:ring-secondary-400/30" }), _jsx(Span, { size: "sm", className: "text-zinc-700 dark:text-zinc-300", children: option.label })] }, option.value));
9
9
  }) }), error && (_jsx(Text, { className: ERROR_BASE, role: "alert", children: error }))] }));
10
10
  }
11
11
  // Toggle variant — pill style