@mohasinac/appkit 3.2.8 → 3.2.10

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 (269) hide show
  1. package/dist/_internal/client/features/filters/filter-load-options.js +12 -9
  2. package/dist/_internal/client/theme/ThemeProvider.js +14 -4
  3. package/dist/_internal/server/features/auth/firebase-identity.d.ts +12 -0
  4. package/dist/_internal/server/features/auth/firebase-identity.js +25 -0
  5. package/dist/_internal/server/features/site-settings/safe-settings.d.ts +12 -0
  6. package/dist/_internal/server/features/site-settings/safe-settings.js +25 -0
  7. package/dist/_internal/shared/features/layout/config.js +7 -7
  8. package/dist/_internal/shared/styles/skeleton.d.ts +8 -8
  9. package/dist/_internal/shared/styles/skeleton.js +10 -10
  10. package/dist/_internal/shared/styles/themed.d.ts +12 -12
  11. package/dist/_internal/shared/styles/themed.js +12 -12
  12. package/dist/features/about/components/AboutView.js +1 -1
  13. package/dist/features/about/components/FAQPageView.js +1 -1
  14. package/dist/features/about/components/FeesView.js +2 -2
  15. package/dist/features/about/components/HowAuctionsWorkView.js +2 -2
  16. package/dist/features/about/components/HowCheckoutWorksView.js +2 -2
  17. package/dist/features/about/components/HowOffersWorkView.js +2 -2
  18. package/dist/features/about/components/HowOrdersWorkView.js +2 -2
  19. package/dist/features/about/components/HowPayoutsWorkView.js +2 -2
  20. package/dist/features/about/components/HowPreOrdersWorkView.js +2 -2
  21. package/dist/features/about/components/HowReviewsWorkView.js +2 -2
  22. package/dist/features/about/components/PublicProfileView.js +3 -3
  23. package/dist/features/about/components/SecurityPrivacyView.js +2 -2
  24. package/dist/features/account/components/AddressBook.js +2 -2
  25. package/dist/features/account/components/AddressesIndexListing.js +1 -1
  26. package/dist/features/account/components/ChatWindow.js +1 -1
  27. package/dist/features/account/components/MessagesView.js +1 -1
  28. package/dist/features/account/components/NotificationBell.js +2 -2
  29. package/dist/features/account/components/NotificationPreferencesPanel.js +1 -1
  30. package/dist/features/account/components/UserSidebar.js +3 -3
  31. package/dist/features/account/components/UserSupportView.js +3 -3
  32. package/dist/features/admin/components/AdminAdEditorView.js +1 -1
  33. package/dist/features/admin/components/AdminAdsView.js +5 -5
  34. package/dist/features/admin/components/AdminAnalyticsView.js +1 -1
  35. package/dist/features/admin/components/AdminBrandsView.js +1 -1
  36. package/dist/features/admin/components/AdminBundlesView.js +2 -2
  37. package/dist/features/admin/components/AdminCarouselEditorView.js +4 -4
  38. package/dist/features/admin/components/AdminCarouselView.js +2 -2
  39. package/dist/features/admin/components/AdminCategoriesView.js +2 -2
  40. package/dist/features/admin/components/AdminContactEditorView.js +1 -1
  41. package/dist/features/admin/components/AdminCouponEditorView.js +1 -1
  42. package/dist/features/admin/components/AdminEmployeeEditorView.js +3 -3
  43. package/dist/features/admin/components/AdminFaqsView.js +1 -1
  44. package/dist/features/admin/components/AdminFeatureEditorView.js +2 -2
  45. package/dist/features/admin/components/AdminFeatureFlagsView.js +1 -1
  46. package/dist/features/admin/components/AdminFeaturesView.js +2 -2
  47. package/dist/features/admin/components/AdminNavigationView.js +2 -2
  48. package/dist/features/admin/components/AdminNotificationsView.js +1 -1
  49. package/dist/features/admin/components/AdminOrderEditorView.js +1 -1
  50. package/dist/features/admin/components/AdminPageHeader.d.ts +1 -1
  51. package/dist/features/admin/components/AdminPageHeader.js +1 -1
  52. package/dist/features/admin/components/AdminReviewsView.js +1 -1
  53. package/dist/features/admin/components/AdminScammerEditorView.js +3 -3
  54. package/dist/features/admin/components/AdminScammersView.js +1 -1
  55. package/dist/features/admin/components/AdminSectionsView.js +1 -1
  56. package/dist/features/admin/components/AdminSessionsView.js +1 -1
  57. package/dist/features/admin/components/AdminSidebar.js +5 -5
  58. package/dist/features/admin/components/AdminSiteSettingsView.js +3 -3
  59. package/dist/features/admin/components/AdminStoreEditorView.js +3 -3
  60. package/dist/features/admin/components/AdminSupportTicketDetailView.js +3 -3
  61. package/dist/features/admin/components/AdminSupportTicketsView.js +2 -2
  62. package/dist/features/admin/components/AdminViewCards.js +5 -5
  63. package/dist/features/admin/components/DataTable.js +1 -1
  64. package/dist/features/admin/components/DrawerFormFooter.js +1 -1
  65. package/dist/features/admin/components/QuickActionsPanel.js +1 -1
  66. package/dist/features/admin/components/analytics/AdminTopProductsTable.js +1 -1
  67. package/dist/features/auctions/components/AuctionDetailPageView.js +2 -2
  68. package/dist/features/auctions/components/CollapsibleBidHistory.js +1 -1
  69. package/dist/features/auctions/components/MarketplaceAuctionCard.js +1 -1
  70. package/dist/features/auth/components/ForgotPasswordView.js +1 -1
  71. package/dist/features/auth/components/Guards.js +1 -1
  72. package/dist/features/auth/components/RegisterForm.js +1 -1
  73. package/dist/features/auth/components/ResetPasswordView.js +1 -1
  74. package/dist/features/auth/components/SocialAuthButtons.js +1 -1
  75. package/dist/features/blog/components/BlogIndexListing.js +1 -1
  76. package/dist/features/blog/components/BlogListView.js +3 -3
  77. package/dist/features/blog/components/BlogPostView.js +1 -1
  78. package/dist/features/cart/components/CartDrawer.js +5 -5
  79. package/dist/features/categories/components/BrandDetailPageView.js +1 -1
  80. package/dist/features/categories/components/BrandDetailTabs.js +1 -1
  81. package/dist/features/categories/components/CategoriesIndexListing.js +2 -2
  82. package/dist/features/categories/components/CategoryDetailPageView.js +1 -1
  83. package/dist/features/categories/components/CategoryDetailTabs.js +1 -1
  84. package/dist/features/categories/components/CategoryGrid.js +3 -3
  85. package/dist/features/categories/components/CategoryTree.js +2 -2
  86. package/dist/features/categories/components/ConcernCard.js +1 -1
  87. package/dist/features/checkout/components/CheckoutStepper.js +1 -1
  88. package/dist/features/classified/components/ClassifiedIndexListing.js +1 -1
  89. package/dist/features/collections/components/CollectionCard.js +1 -1
  90. package/dist/features/collections/hooks/useCollections.js +12 -12
  91. package/dist/features/contact/components/ContactForm.js +1 -1
  92. package/dist/features/copilot/components/AdminCopilotView.js +5 -5
  93. package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +1 -1
  94. package/dist/features/events/components/AdminEventEntriesView.js +1 -1
  95. package/dist/features/events/components/EventCard.js +1 -1
  96. package/dist/features/events/components/EventPollWidget.js +1 -1
  97. package/dist/features/events/components/EventStatusBadge.js +1 -1
  98. package/dist/features/events/components/EventsIndexListing.js +1 -1
  99. package/dist/features/faq/components/ContactCTA.js +2 -2
  100. package/dist/features/faq/components/FAQAccordion.js +4 -4
  101. package/dist/features/faq/components/FAQCategorySidebar.js +2 -2
  102. package/dist/features/faq/components/FAQHelpfulButtons.js +4 -4
  103. package/dist/features/faq/components/RelatedFAQs.js +1 -1
  104. package/dist/features/filters/AsyncFacetSection.js +3 -3
  105. package/dist/features/filters/FilterFacetSection.js +5 -5
  106. package/dist/features/filters/RangeFilter.js +3 -3
  107. package/dist/features/filters/SwitchFilter.js +2 -2
  108. package/dist/features/forms/Checkbox.js +1 -1
  109. package/dist/features/forms/Input.js +2 -2
  110. package/dist/features/forms/Radio.js +2 -2
  111. package/dist/features/forms/Select.js +1 -1
  112. package/dist/features/forms/Slider.js +1 -1
  113. package/dist/features/forms/Textarea.js +1 -1
  114. package/dist/features/forms/Toggle.js +3 -3
  115. package/dist/features/forms/utils.d.ts +4 -4
  116. package/dist/features/forms/utils.js +4 -4
  117. package/dist/features/homepage/components/AdSlot.js +1 -1
  118. package/dist/features/homepage/components/AdvertisementBanner.js +3 -3
  119. package/dist/features/homepage/components/BrandsSection.js +2 -2
  120. package/dist/features/homepage/components/GoogleReviewsSection.js +1 -1
  121. package/dist/features/homepage/components/HeroSection.js +1 -1
  122. package/dist/features/homepage/components/HomepageCustomerReviewsSection.js +1 -1
  123. package/dist/features/homepage/components/HowItWorksSection.js +1 -1
  124. package/dist/features/homepage/components/ShopByCategorySection.js +2 -2
  125. package/dist/features/homepage/components/SiteFeaturesSection.js +1 -1
  126. package/dist/features/homepage/components/SocialPostCard.js +1 -1
  127. package/dist/features/homepage/components/StatsCounterSection.js +1 -1
  128. package/dist/features/homepage/components/TrustIndicatorsSection.js +1 -1
  129. package/dist/features/homepage/constants/hero-carousel-styles.d.ts +3 -3
  130. package/dist/features/homepage/constants/hero-carousel-styles.js +3 -3
  131. package/dist/features/homepage/hooks/useActiveAd.d.ts +1 -3
  132. package/dist/features/homepage/hooks/useActiveAd.js +9 -17
  133. package/dist/features/layout/AppLayoutShell.js +12 -12
  134. package/dist/features/layout/AutoBreadcrumbs.js +1 -1
  135. package/dist/features/layout/BackToTop.js +2 -2
  136. package/dist/features/layout/BottomActions.js +8 -8
  137. package/dist/features/layout/BottomNavItem.js +1 -1
  138. package/dist/features/layout/BottomNavLayout.js +1 -1
  139. package/dist/features/layout/BottomNavbar.d.ts +1 -1
  140. package/dist/features/layout/BottomNavbar.js +2 -2
  141. package/dist/features/layout/BottomSheet.js +1 -1
  142. package/dist/features/layout/Breadcrumbs.js +2 -2
  143. package/dist/features/layout/FooterLayout.js +2 -2
  144. package/dist/features/layout/MainNavbar.js +1 -1
  145. package/dist/features/layout/NavItem.js +1 -1
  146. package/dist/features/layout/NavbarLayout.js +3 -3
  147. package/dist/features/layout/SidebarLayout.js +1 -1
  148. package/dist/features/layout/TitleBarLayout.js +3 -3
  149. package/dist/features/live/components/LiveItemsIndexListing.js +1 -1
  150. package/dist/features/loyalty/components/CoinsDisplay.js +1 -1
  151. package/dist/features/loyalty/hooks/useLoyaltyBalance.js +11 -3
  152. package/dist/features/media/AvatarUpload.js +1 -1
  153. package/dist/features/media/MediaPickerModal.js +1 -1
  154. package/dist/features/media/components/MediaSlider.js +1 -1
  155. package/dist/features/media/finalize.d.ts +12 -1
  156. package/dist/features/media/finalize.js +64 -11
  157. package/dist/features/media/modals/ImageCropModal.js +1 -1
  158. package/dist/features/media/modals/ImageEditor.js +1 -1
  159. package/dist/features/media/repository/media-assets.repository.d.ts +33 -0
  160. package/dist/features/media/repository/media-assets.repository.js +43 -0
  161. package/dist/features/media/upload/MediaUploadField.js +1 -1
  162. package/dist/features/messages/hooks/useConversation.js +12 -17
  163. package/dist/features/messages/hooks/useConversations.js +3 -5
  164. package/dist/features/orders/components/MarketplaceOrderCard.js +1 -1
  165. package/dist/features/orders/components/OrdersList.js +3 -3
  166. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +1 -1
  167. package/dist/features/pre-orders/components/PreOrderBadge.js +1 -1
  168. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +2 -2
  169. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +1 -1
  170. package/dist/features/pre-orders/hooks/usePreOrders.js +12 -12
  171. package/dist/features/products/columns/productTableColumns.js +3 -3
  172. package/dist/features/products/components/BidHistory.js +1 -1
  173. package/dist/features/products/components/CompareOverlay.js +9 -9
  174. package/dist/features/products/components/CustomSectionTabContent.js +1 -1
  175. package/dist/features/products/components/CustomSectionsEditor.js +1 -1
  176. package/dist/features/products/components/FeatureBadge.js +2 -2
  177. package/dist/features/products/components/GroupSettingsPanel.js +2 -2
  178. package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -2
  179. package/dist/features/products/components/PrizeDrawsIndexListing.js +1 -1
  180. package/dist/features/products/components/ProductDetailPageView.js +4 -4
  181. package/dist/features/products/components/ProductFeatureBadges.js +2 -2
  182. package/dist/features/products/components/ProductFeaturesSelector.js +4 -4
  183. package/dist/features/products/components/ProductGalleryClient.js +1 -1
  184. package/dist/features/products/components/ProductGrid.js +8 -8
  185. package/dist/features/products/components/ProductTabs.js +1 -1
  186. package/dist/features/products/components/ProductTabsShell.js +1 -1
  187. package/dist/features/products/components/ShareButton.js +1 -1
  188. package/dist/features/products/components/ShowGroupSection.js +2 -2
  189. package/dist/features/products/components/SublistingCarouselSection.js +2 -2
  190. package/dist/features/promotions/components/CouponCard.js +2 -2
  191. package/dist/features/promotions/components/CouponsIndexListing.js +2 -2
  192. package/dist/features/reviews/components/ReviewDetailPageView.js +1 -1
  193. package/dist/features/reviews/components/ReviewDetailShell.js +5 -5
  194. package/dist/features/reviews/components/ReviewModal.js +1 -1
  195. package/dist/features/reviews/components/ReviewSummary.js +2 -2
  196. package/dist/features/reviews/components/ReviewsIndexListing.js +1 -1
  197. package/dist/features/reviews/components/ReviewsList.js +2 -2
  198. package/dist/features/scams/components/ScamRegistryView.js +2 -2
  199. package/dist/features/search/components/Search.js +11 -11
  200. package/dist/features/search/components/SearchFiltersRow.js +1 -1
  201. package/dist/features/search/components/SearchResultsSection.js +2 -2
  202. package/dist/features/seller/components/SellerAddressesView.js +4 -4
  203. package/dist/features/seller/components/SellerAnalyticsAlertsView.js +1 -1
  204. package/dist/features/seller/components/SellerCouponEditorView.js +1 -1
  205. package/dist/features/seller/components/SellerCouponsView.js +1 -1
  206. package/dist/features/seller/components/SellerFeaturesView.js +2 -2
  207. package/dist/features/seller/components/SellerGoogleReviewsView.js +1 -1
  208. package/dist/features/seller/components/SellerOrdersView.js +1 -1
  209. package/dist/features/seller/components/SellerPayoutMethodsView.js +1 -1
  210. package/dist/features/seller/components/SellerSidebar.js +4 -4
  211. package/dist/features/seller/components/analytics/SellerRevenueChart.js +1 -1
  212. package/dist/features/seller/components/analytics/SellerTopProducts.js +1 -1
  213. package/dist/features/site-settings/components/ActionPermissionsManager.js +2 -2
  214. package/dist/features/site-settings/components/NavPermissionsManager.js +1 -1
  215. package/dist/features/stores/components/InteractiveStoreCard.js +3 -3
  216. package/dist/features/stores/components/StoreHeader.js +2 -2
  217. package/dist/features/stores/components/StoreNavTabs.js +2 -2
  218. package/dist/features/stores/components/StorePreOrdersListing.js +1 -1
  219. package/dist/features/stores/components/StoreReviewsListing.js +1 -1
  220. package/dist/features/stores/components/StoresIndexListing.js +1 -1
  221. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +2 -2
  222. package/dist/features/wishlist/components/WishlistPage.js +2 -2
  223. package/dist/features/wishlist/hooks/useWishlistCount.js +5 -13
  224. package/dist/http/index.d.ts +1 -0
  225. package/dist/http/index.js +1 -0
  226. package/dist/http/retry.d.ts +1 -0
  227. package/dist/http/retry.js +26 -0
  228. package/dist/index.d.ts +4 -0
  229. package/dist/index.js +8 -0
  230. package/dist/next/ErrorBoundary.js +1 -1
  231. package/dist/providers/storage-firebase/provider.js +109 -55
  232. package/dist/repositories/index.d.ts +2 -0
  233. package/dist/repositories/index.js +2 -0
  234. package/dist/seed/site-settings-seed-data.js +476 -0
  235. package/dist/server.d.ts +4 -0
  236. package/dist/server.js +9 -0
  237. package/dist/styles.css +1 -1
  238. package/dist/tailwind-utilities.css +1 -1
  239. package/dist/tokens/index.d.ts +6 -6
  240. package/dist/tokens/index.js +59 -59
  241. package/dist/ui/DataTable.js +3 -3
  242. package/dist/ui/components/Avatar.js +1 -1
  243. package/dist/ui/components/BaseListingCard.js +7 -7
  244. package/dist/ui/components/Button.js +3 -3
  245. package/dist/ui/components/DetailPageGallery.js +3 -3
  246. package/dist/ui/components/DetailPageHero.js +1 -1
  247. package/dist/ui/components/DetailPageTabs.js +4 -4
  248. package/dist/ui/components/FilterChipGroup.js +2 -2
  249. package/dist/ui/components/Input.js +1 -1
  250. package/dist/ui/components/Layout.d.ts +2 -2
  251. package/dist/ui/components/ListingFilterDrawer.js +2 -2
  252. package/dist/ui/components/ListingToolbar.js +6 -6
  253. package/dist/ui/components/LoginRequiredModal.js +1 -1
  254. package/dist/ui/components/Modal.js +1 -1
  255. package/dist/ui/components/NavbarChevron.js +1 -1
  256. package/dist/ui/components/PageLoader.js +3 -3
  257. package/dist/ui/components/Radio.js +1 -1
  258. package/dist/ui/components/RichTextEditor.js +1 -1
  259. package/dist/ui/components/Select.js +1 -1
  260. package/dist/ui/components/SettingsSection.js +3 -3
  261. package/dist/ui/components/SideModal.js +1 -1
  262. package/dist/ui/components/Slider.js +2 -2
  263. package/dist/ui/components/StatsGrid.js +1 -1
  264. package/dist/ui/components/Typography.js +3 -3
  265. package/dist/ui/components/surface-tokens.d.ts +11 -11
  266. package/dist/ui/components/surface-tokens.js +12 -12
  267. package/dist/utils/safe-fire-forget.d.ts +14 -0
  268. package/dist/utils/safe-fire-forget.js +23 -0
  269. package/package.json +1 -1
@@ -24,7 +24,7 @@ function ListingThumb({ listing, isCurrent, }) {
24
24
  const price = formatCurrency(listing.price, listing.currency ?? "INR");
25
25
  return (_jsxs(Link, { href: href, "aria-label": listing.title, className: "flex flex-col items-center gap-1.5 flex-shrink-0 w-16 group", children: [_jsx("div", { className: `w-14 h-14 rounded-full overflow-hidden border-2 transition-all ${isCurrent
26
26
  ? "border-[var(--appkit-color-primary)] ring-2 ring-[var(--appkit-color-primary)]/30"
27
- : "border-zinc-200 dark:border-zinc-700 group-hover:border-[var(--appkit-color-primary)]"}`, children: image ? (
27
+ : "border-[var(--appkit-color-border)] group-hover:border-[var(--appkit-color-primary)]"}`, children: image ? (
28
28
  // eslint-disable-next-line @next/next/no-img-element
29
29
  _jsx("img", { src: image, alt: listing.title, className: "w-full h-full object-cover", loading: "lazy" })) : (_jsx(Row, { textSize: "xs", color: "faint", className: "w-full h-full", surface: "subtle", align: "center", justify: "center", children: "\u00E2\u2014\u00AF" })) }), _jsx(Text, { className: "text-[10px] leading-tight line-clamp-2 w-full", color: "muted", align: "center", children: listing.title }), _jsx(Text, { className: "text-[10px]", color: "primary", weight: "semibold", children: price })] }));
30
30
  }
@@ -54,5 +54,5 @@ export function SublistingCarouselSection({ sublistingCategoryId, currentListing
54
54
  if (others.length === 0)
55
55
  return null;
56
56
  const label = category?.name ?? "More listings like this";
57
- return (_jsxs(Div, { className: `${__O.hidden}`, surface: "muted", rounded: "xl", border: "default", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "w-full flex items-center justify-between px-4 py-3 text-left hover:bg-zinc-100/70 dark:hover:bg-zinc-800/70 transition-colors", "aria-expanded": open, children: [_jsxs(Row, { align: "center", gap: "xs", children: [_jsx(Span, { size: "xs", className: "mr-1", color: "faint", children: open ? "â–¼" : "â–¶" }), _jsxs(Text, { size: "sm", weight: "medium", color: "primary", children: ["More listings like this:", " ", _jsx(Span, { className: "text-[var(--appkit-color-primary)]", children: label })] }), _jsx(Span, { size: "xs", className: "ml-1", rounded: "full", padding: "pill-xs", surface: "subtle", color: "muted", children: listings.length })] }), category && (_jsx(Link, { href: String(ROUTES.PUBLIC.SUBLISTING_CATEGORY(category.slug)), onClick: (e) => e.stopPropagation(), className: "text-xs text-[var(--appkit-color-primary)] hover:underline ml-3 flex-shrink-0", children: "View all \u00E2\u2020\u2019" }))] }), open && (_jsx(Div, { className: `pb-[1rem] pt-[0.25rem] ${__O.xAuto}`, padding: "x-md", children: _jsx(Row, { gap: "3", className: "min-w-0", children: listings.map((listing) => (_jsx(ListingThumb, { listing: listing, isCurrent: listing.id === currentListingId }, listing.id))) }) }))] }));
57
+ return (_jsxs(Div, { className: `${__O.hidden}`, surface: "muted", rounded: "xl", border: "default", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "w-full flex items-center justify-between px-4 py-3 text-left hover:bg-[var(--appkit-color-surface)]/70 hover:bg-[var(--appkit-color-surface-elevated)]/70 transition-colors", "aria-expanded": open, children: [_jsxs(Row, { align: "center", gap: "xs", children: [_jsx(Span, { size: "xs", className: "mr-1", color: "faint", children: open ? "â–¼" : "â–¶" }), _jsxs(Text, { size: "sm", weight: "medium", color: "primary", children: ["More listings like this:", " ", _jsx(Span, { className: "text-[var(--appkit-color-primary)]", children: label })] }), _jsx(Span, { size: "xs", className: "ml-1", rounded: "full", padding: "pill-xs", surface: "subtle", color: "muted", children: listings.length })] }), category && (_jsx(Link, { href: String(ROUTES.PUBLIC.SUBLISTING_CATEGORY(category.slug)), onClick: (e) => e.stopPropagation(), className: "text-xs text-[var(--appkit-color-primary)] hover:underline ml-3 flex-shrink-0", children: "View all \u00E2\u2020\u2019" }))] }), open && (_jsx(Div, { className: `pb-[1rem] pt-[0.25rem] ${__O.xAuto}`, padding: "x-md", children: _jsx(Row, { gap: "3", className: "min-w-0", children: listings.map((listing) => (_jsx(ListingThumb, { listing: listing, isCurrent: listing.id === currentListingId }, listing.id))) }) }))] }));
58
58
  }
@@ -5,7 +5,7 @@ import { Pencil, Trash2, ToggleLeft, ToggleRight } from "lucide-react";
5
5
  import { Badge, BaseListingCard, ConfirmDeleteModal, Div, Row, Span, Stack, Text } from "../../../ui";
6
6
  import { useLongPress } from "../../../react/hooks/useLongPress";
7
7
  const CLS_TOGGLE_ON = "h-4 w-4 text-success dark:text-success";
8
- const CLS_DELETE_BTN = "rounded-lg p-1.5 text-zinc-500 dark:text-zinc-400 hover:bg-error-surface dark:hover:bg-error-surface hover:text-error dark:hover:text-error transition-colors disabled:opacity-50";
8
+ const CLS_DELETE_BTN = "rounded-lg p-1.5 text-[var(--appkit-color-text-muted)] hover:bg-error-surface dark:hover:bg-error-surface hover:text-error dark:hover:text-error transition-colors disabled:opacity-50";
9
9
  const TYPE_COLORS = {
10
10
  percentage: { card: "bg-purple-50 border-purple-200 dark:bg-purple-950/30 dark:border-purple-800", code: "bg-purple-100 dark:bg-purple-900/40 text-purple-800 dark:text-purple-200 border-purple-300 dark:border-purple-700" },
11
11
  fixed: { card: "bg-success-surface border-success dark:bg-success-surface dark:border-success", code: "bg-success-surface dark:bg-success-surface text-success dark:text-success border-success dark:border-success" },
@@ -159,7 +159,7 @@ export function CouponCard({ coupon, labels: labelsProp, onCopy, className = "",
159
159
  setBusy(null);
160
160
  }
161
161
  };
162
- return (_jsxs(Stack, { className: `group relative h-full border-2 ${colors.card} ${isSelected ? "ring-2 ring-primary" : ""} ${!n.isActive ? "opacity-70" : ""} ${className}`, rounded: "xl", padding: "md", onMouseDown: onSelect && !isSelected ? longPress.onMouseDown : undefined, onMouseUp: onSelect && !isSelected ? longPress.onMouseUp : undefined, onMouseLeave: onSelect && !isSelected ? longPress.onMouseLeave : undefined, onTouchStart: onSelect && !isSelected ? longPress.onTouchStart : undefined, onTouchEnd: onSelect && !isSelected ? longPress.onTouchEnd : undefined, children: [onSelect && (_jsx(BaseListingCard.Checkbox, { selected: isSelected, onSelect: (e) => { e.preventDefault(); onSelect(n.id, !isSelected); }, label: isSelected ? "Deselect coupon" : "Select coupon", position: "top-2 right-2", className: selectable || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), (hasAdminActions || n.scope) && (_jsxs(Row, { gap: "xs", wrap: true, className: "mb-2", children: [_jsx(Badge, { variant: n.isActive ? "active" : "inactive", size: "xs", className: "text-[10px] uppercase tracking-wide", children: n.isActive ? labels.active : labels.inactive }), n.scope && (_jsx(Span, { layout: "inline-flex", weight: "semibold", className: "bg-neutral-200/70 text-[10px] tracking-wide dark:bg-neutral-700/60", rounded: "full", padding: "pill-xs", color: "primary", transform: "uppercase", children: n.scope }))] })), _jsxs(Div, { className: "mb-3", children: [_jsx(Text, { className: "font-extrabold tracking-tight leading-none", size: "2xl", children: discountLabel }), n.name && (_jsx(Text, { className: "mt-0.5 opacity-80", size: "sm", weight: "medium", children: n.name }))] }), n.description && (_jsx(Text, { className: "opacity-60 mb-3", size: "xs", children: n.description })), _jsxs(Row, { className: `border border-dashed ${colors.code}`, align: "center", gap: "sm", rounded: "lg", padding: "inlineSm", children: [_jsx(Span, { size: "sm", weight: "bold", className: "flex-1 font-mono tracking-widest select-all", transform: "uppercase", children: n.code || "—" }), n.code && (_jsx("button", { type: "button", onClick: handleCopy, className: "shrink-0 rounded-md px-2.5 py-1 text-xs font-semibold transition-all hover:opacity-80 active:scale-95 bg-white/60 dark:bg-black/20 border border-current/20", "aria-label": "Copy coupon code", children: copied ? labels.copied : labels.copy }))] }), showClaim && n.code && n.isActive && (_jsx(Div, { className: "mt-2", children: _jsx("button", { type: "button", onClick: handleClaim, disabled: claiming, className: "w-full rounded-md px-3 py-1.5 text-xs font-semibold transition-all active:scale-95 bg-[var(--appkit-color-primary-700)] text-[var(--appkit-color-text-on-primary)] hover:bg-[var(--appkit-color-primary-800)] disabled:opacity-50", "aria-label": `Claim coupon ${n.code} and apply at checkout`, children: claiming ? labels.claiming : labels.claim }) })), _jsxs(Row, { textSize: "xs", wrap: true, gap: "sm", className: "opacity-60 mt-2", children: [n.minOrderAmount ? (_jsxs(Span, { children: [labels.minOrder, ": \u20B9", (n.minOrderAmount / 100).toFixed(0)] })) : null, expiry && (_jsxs(Span, { children: [labels.expires, ": ", expiry] })), n.usageLimit ? (_jsxs(Span, { children: [n.usageCount, "/", n.usageLimit, " ", labels.used] })) : n.usageCount > 0 ? (_jsxs(Span, { children: [n.usageCount, " ", labels.used] })) : null] }), hasAdminActions && (_jsxs(Row, { gap: "xs", justify: "end", className: "mt-auto", padding: "t-sm", children: [onEdit && (_jsx("button", { type: "button", onClick: () => onEdit(n.id), title: labels.edit, "aria-label": labels.edit, className: "rounded-lg p-1.5 text-zinc-500 dark:text-zinc-400 hover:bg-white/60 dark:hover:bg-black/30 hover:text-zinc-800 dark:hover:text-zinc-200 transition-colors", children: _jsx(Pencil, { className: "h-4 w-4" }) })), onToggleActive && (_jsx("button", { type: "button", onClick: handleToggle, disabled: busy === "toggle", title: n.isActive ? labels.deactivate : labels.activate, "aria-label": n.isActive ? labels.deactivate : labels.activate, className: "rounded-lg p-1.5 text-zinc-500 dark:text-zinc-400 hover:bg-white/60 dark:hover:bg-black/30 transition-colors disabled:opacity-50", children: n.isActive
162
+ return (_jsxs(Stack, { className: `group relative h-full border-2 ${colors.card} ${isSelected ? "ring-2 ring-primary" : ""} ${!n.isActive ? "opacity-70" : ""} ${className}`, rounded: "xl", padding: "md", onMouseDown: onSelect && !isSelected ? longPress.onMouseDown : undefined, onMouseUp: onSelect && !isSelected ? longPress.onMouseUp : undefined, onMouseLeave: onSelect && !isSelected ? longPress.onMouseLeave : undefined, onTouchStart: onSelect && !isSelected ? longPress.onTouchStart : undefined, onTouchEnd: onSelect && !isSelected ? longPress.onTouchEnd : undefined, children: [onSelect && (_jsx(BaseListingCard.Checkbox, { selected: isSelected, onSelect: (e) => { e.preventDefault(); onSelect(n.id, !isSelected); }, label: isSelected ? "Deselect coupon" : "Select coupon", position: "top-2 right-2", className: selectable || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), (hasAdminActions || n.scope) && (_jsxs(Row, { gap: "xs", wrap: true, className: "mb-2", children: [_jsx(Badge, { variant: n.isActive ? "active" : "inactive", size: "xs", className: "text-[10px] uppercase tracking-wide", children: n.isActive ? labels.active : labels.inactive }), n.scope && (_jsx(Span, { layout: "inline-flex", weight: "semibold", className: "bg-neutral-200/70 text-[10px] tracking-wide bg-[var(--appkit-color-border)]/60", rounded: "full", padding: "pill-xs", color: "primary", transform: "uppercase", children: n.scope }))] })), _jsxs(Div, { className: "mb-3", children: [_jsx(Text, { className: "font-extrabold tracking-tight leading-none", size: "2xl", children: discountLabel }), n.name && (_jsx(Text, { className: "mt-0.5 opacity-80", size: "sm", weight: "medium", children: n.name }))] }), n.description && (_jsx(Text, { className: "opacity-60 mb-3", size: "xs", children: n.description })), _jsxs(Row, { className: `border border-dashed ${colors.code}`, align: "center", gap: "sm", rounded: "lg", padding: "inlineSm", children: [_jsx(Span, { size: "sm", weight: "bold", className: "flex-1 font-mono tracking-widest select-all", transform: "uppercase", children: n.code || "—" }), n.code && (_jsx("button", { type: "button", onClick: handleCopy, className: "shrink-0 rounded-md px-2.5 py-1 text-xs font-semibold transition-all hover:opacity-80 active:scale-95 bg-white/60 dark:bg-black/20 border border-current/20", "aria-label": "Copy coupon code", children: copied ? labels.copied : labels.copy }))] }), showClaim && n.code && n.isActive && (_jsx(Div, { className: "mt-2", children: _jsx("button", { type: "button", onClick: handleClaim, disabled: claiming, className: "w-full rounded-md px-3 py-1.5 text-xs font-semibold transition-all active:scale-95 bg-[var(--appkit-color-primary-700)] text-[var(--appkit-color-text-on-primary)] hover:bg-[var(--appkit-color-primary-800)] disabled:opacity-50", "aria-label": `Claim coupon ${n.code} and apply at checkout`, children: claiming ? labels.claiming : labels.claim }) })), _jsxs(Row, { textSize: "xs", wrap: true, gap: "sm", className: "opacity-60 mt-2", children: [n.minOrderAmount ? (_jsxs(Span, { children: [labels.minOrder, ": \u20B9", (n.minOrderAmount / 100).toFixed(0)] })) : null, expiry && (_jsxs(Span, { children: [labels.expires, ": ", expiry] })), n.usageLimit ? (_jsxs(Span, { children: [n.usageCount, "/", n.usageLimit, " ", labels.used] })) : n.usageCount > 0 ? (_jsxs(Span, { children: [n.usageCount, " ", labels.used] })) : null] }), hasAdminActions && (_jsxs(Row, { gap: "xs", justify: "end", className: "mt-auto", padding: "t-sm", children: [onEdit && (_jsx("button", { type: "button", onClick: () => onEdit(n.id), title: labels.edit, "aria-label": labels.edit, className: "rounded-lg p-1.5 text-[var(--appkit-color-text-muted)] hover:bg-white/60 dark:hover:bg-black/30 hover:text-zinc-800 hover:text-[var(--appkit-color-text-muted)] transition-colors", children: _jsx(Pencil, { className: "h-4 w-4" }) })), onToggleActive && (_jsx("button", { type: "button", onClick: handleToggle, disabled: busy === "toggle", title: n.isActive ? labels.deactivate : labels.activate, "aria-label": n.isActive ? labels.deactivate : labels.activate, className: "rounded-lg p-1.5 text-[var(--appkit-color-text-muted)] hover:bg-white/60 dark:hover:bg-black/30 transition-colors disabled:opacity-50", children: n.isActive
163
163
  ? _jsx(ToggleRight, { className: CLS_TOGGLE_ON })
164
164
  : _jsx(ToggleLeft, { className: "h-4 w-4" }) })), onDelete && (_jsx("button", { type: "button", onClick: () => setDeleteConfirmOpen(true), disabled: busy === "delete", title: labels.delete, "aria-label": labels.delete, className: CLS_DELETE_BTN, children: _jsx(Trash2, { className: "h-4 w-4" }) }))] })), deleteConfirmOpen && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Coupon", message: labels.deleteConfirm, onConfirm: handleDeleteConfirmed, onClose: () => setDeleteConfirmOpen(false), isDeleting: busy === "delete" }))] }));
165
165
  }
@@ -95,12 +95,12 @@ export function CouponsIndexListing({ initialCoupons, storeSlug, storeId, }) {
95
95
  };
96
96
  return (_jsxs(Div, { className: "min-h-[40vh]", children: [_jsxs(Div, { border: "default", paddingY: "y-xs-tall", className: "sticky top-[var(--header-height,0px)] z-20 border-b backdrop-blur-sm", surface: "default", padding: "x-md", children: [_jsxs(Row, { gap: "xs", className: "max-w-full", children: [_jsxs("button", { type: "button", onClick: openFilters, className: `flex shrink-0 items-center gap-2 rounded-lg border px-3.5 py-2 text-sm font-medium transition-colors ${hasActiveFilters
97
97
  ? "border-primary bg-primary-50 text-primary-700 dark:bg-primary-900/30 dark:text-primary-300"
98
- : "border-zinc-300 dark:border-slate-600 text-zinc-700 dark:text-zinc-200 hover:bg-zinc-50 dark:hover:bg-slate-800"}`, children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), _jsxs(Span, { className: "hidden sm:inline", children: ["Filters", hasActiveFilters ? " •" : ""] })] }), _jsxs(Row, { surface: "default", className: `flex-1 ${__O.hidden}`, border: "strong", rounded: "lg", children: [_jsx("input", { type: "text", value: searchInput, onChange: (e) => setSearchInput(e.target.value), onKeyDown: handleKeyDown, placeholder: "Search by name or description\u2026", className: "min-w-0 flex-1 bg-transparent px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 placeholder-zinc-400 outline-none" }), searchInput && (_jsx("button", { type: "button", onClick: () => { setSearchInput(""); table.set(TABLE_KEYS.QUERY, ""); }, className: "p-2 text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300", "aria-label": "Clear search", children: _jsx(X, { className: "h-3.5 w-3.5" }) })), _jsx("button", { type: "button", onClick: commitSearch, className: "flex shrink-0 items-center justify-center px-3 py-2 text-zinc-400 hover:text-primary dark:hover:text-primary-400 transition-colors", "aria-label": "Search", children: _jsx(Search, { className: "h-4 w-4" }) })] }), _jsxs(Row, { color: "muted", textSize: "sm", gap: "xs", className: "shrink-0", children: [_jsx(Span, { className: "hidden md:inline whitespace-nowrap", children: "Sort by" }), _jsx(SortDropdown, { value: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, onChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, options: COUPON_SORT_OPTIONS })] })] }), hasActiveFilters && (_jsxs(Row, { gap: "xs", wrap: true, className: "mt-2", children: [activeType && (_jsxs(Span, { layout: "flex", gap: "xs", size: "xs", weight: "medium", className: "bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300", rounded: "full", padding: "pill-sm-tall", children: [COUPON_TYPES.find((t) => t.value === activeType)?.label ?? activeType, _jsx(Button, { variant: "ghost", type: "button", onClick: () => { table.set(TABLE_KEYS.TYPE, ""); }, "aria-label": "Remove type filter", className: CLS_CHIP_BTN, children: _jsx(X, { className: "h-3 w-3" }) })] })), table.get(TABLE_KEYS.DATE_FROM) && (_jsxs(Span, { layout: "flex", gap: "xs", size: "xs", weight: "medium", className: "bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300", rounded: "full", padding: "pill-sm-tall", children: ["From: ", table.get(TABLE_KEYS.DATE_FROM), _jsx(Button, { variant: "ghost", type: "button", onClick: () => { table.set(TABLE_KEYS.DATE_FROM, ""); }, "aria-label": "Remove from-date filter", className: CLS_CHIP_BTN, children: _jsx(X, { className: "h-3 w-3" }) })] })), table.get(TABLE_KEYS.DATE_TO) && (_jsxs(Span, { layout: "flex", gap: "xs", size: "xs", weight: "medium", className: "bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300", rounded: "full", padding: "pill-sm-tall", children: ["To: ", table.get(TABLE_KEYS.DATE_TO), _jsx(Button, { variant: "ghost", type: "button", onClick: () => { table.set(TABLE_KEYS.DATE_TO, ""); }, "aria-label": "Remove to-date filter", className: CLS_CHIP_BTN, children: _jsx(X, { className: "h-3 w-3" }) })] })), _jsx("button", { type: "button", onClick: clearFilters, className: "text-xs text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-300 underline", children: "Clear all" })] }))] }), _jsxs(Div, { paddingY: "y-lg", paddingX: "x-md", children: [isLoading ? (_jsx(Grid, { gap: "sm", className: "md:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsxs(Stack, { border: "skeleton", gap: "sm", rounded: "xl", padding: "md", className: "animate-pulse", children: [_jsx(Div, { className: "h-6 w-2/3", surface: "subtle", rounded: "default" }), _jsx(Div, { className: "h-4 w-full", surface: "subtle", rounded: "default" }), _jsx(Div, { className: "h-3 w-1/2", surface: "subtle", rounded: "default" })] }, i))) })) : displayCoupons.length === 0 ? (_jsx(Div, { className: "text-center", padding: "y-4xl", children: _jsx(Text, { color: "faint", children: "No coupons match your search." }) })) : (_jsx(Grid, { gap: "sm", className: "md:grid-cols-2 lg:grid-cols-3", children: displayCoupons.map((coupon) => (_jsx(CouponCard, { coupon: coupon, labels: {
98
+ : "border-[var(--appkit-color-border)] text-[var(--appkit-color-text-muted)] hover:bg-zinc-50 hover:bg-[var(--appkit-color-surface-elevated)]"}`, children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), _jsxs(Span, { className: "hidden sm:inline", children: ["Filters", hasActiveFilters ? " •" : ""] })] }), _jsxs(Row, { surface: "default", className: `flex-1 ${__O.hidden}`, border: "strong", rounded: "lg", children: [_jsx("input", { type: "text", value: searchInput, onChange: (e) => setSearchInput(e.target.value), onKeyDown: handleKeyDown, placeholder: "Search by name or description\u2026", className: "min-w-0 flex-1 bg-transparent px-3 py-2 text-sm text-[var(--appkit-color-text)] placeholder-zinc-400 outline-none" }), searchInput && (_jsx("button", { type: "button", onClick: () => { setSearchInput(""); table.set(TABLE_KEYS.QUERY, ""); }, className: "p-2 text-zinc-400 hover:text-[var(--appkit-color-text-muted)] hover:text-[var(--appkit-color-text-muted)]", "aria-label": "Clear search", children: _jsx(X, { className: "h-3.5 w-3.5" }) })), _jsx("button", { type: "button", onClick: commitSearch, className: "flex shrink-0 items-center justify-center px-3 py-2 text-zinc-400 hover:text-primary dark:hover:text-primary-400 transition-colors", "aria-label": "Search", children: _jsx(Search, { className: "h-4 w-4" }) })] }), _jsxs(Row, { color: "muted", textSize: "sm", gap: "xs", className: "shrink-0", children: [_jsx(Span, { className: "hidden md:inline whitespace-nowrap", children: "Sort by" }), _jsx(SortDropdown, { value: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, onChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, options: COUPON_SORT_OPTIONS })] })] }), hasActiveFilters && (_jsxs(Row, { gap: "xs", wrap: true, className: "mt-2", children: [activeType && (_jsxs(Span, { layout: "flex", gap: "xs", size: "xs", weight: "medium", className: "bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300", rounded: "full", padding: "pill-sm-tall", children: [COUPON_TYPES.find((t) => t.value === activeType)?.label ?? activeType, _jsx(Button, { variant: "ghost", type: "button", onClick: () => { table.set(TABLE_KEYS.TYPE, ""); }, "aria-label": "Remove type filter", className: CLS_CHIP_BTN, children: _jsx(X, { className: "h-3 w-3" }) })] })), table.get(TABLE_KEYS.DATE_FROM) && (_jsxs(Span, { layout: "flex", gap: "xs", size: "xs", weight: "medium", className: "bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300", rounded: "full", padding: "pill-sm-tall", children: ["From: ", table.get(TABLE_KEYS.DATE_FROM), _jsx(Button, { variant: "ghost", type: "button", onClick: () => { table.set(TABLE_KEYS.DATE_FROM, ""); }, "aria-label": "Remove from-date filter", className: CLS_CHIP_BTN, children: _jsx(X, { className: "h-3 w-3" }) })] })), table.get(TABLE_KEYS.DATE_TO) && (_jsxs(Span, { layout: "flex", gap: "xs", size: "xs", weight: "medium", className: "bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300", rounded: "full", padding: "pill-sm-tall", children: ["To: ", table.get(TABLE_KEYS.DATE_TO), _jsx(Button, { variant: "ghost", type: "button", onClick: () => { table.set(TABLE_KEYS.DATE_TO, ""); }, "aria-label": "Remove to-date filter", className: CLS_CHIP_BTN, children: _jsx(X, { className: "h-3 w-3" }) })] })), _jsx("button", { type: "button", onClick: clearFilters, className: "text-xs text-[var(--appkit-color-text-muted)] hover:text-[var(--appkit-color-text-muted)] underline", children: "Clear all" })] }))] }), _jsxs(Div, { paddingY: "y-lg", paddingX: "x-md", children: [isLoading ? (_jsx(Grid, { gap: "sm", className: "md:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsxs(Stack, { border: "skeleton", gap: "sm", rounded: "xl", padding: "md", className: "animate-pulse", children: [_jsx(Div, { className: "h-6 w-2/3", surface: "subtle", rounded: "default" }), _jsx(Div, { className: "h-4 w-full", surface: "subtle", rounded: "default" }), _jsx(Div, { className: "h-3 w-1/2", surface: "subtle", rounded: "default" })] }, i))) })) : displayCoupons.length === 0 ? (_jsx(Div, { className: "text-center", padding: "y-4xl", children: _jsx(Text, { color: "faint", children: "No coupons match your search." }) })) : (_jsx(Grid, { gap: "sm", className: "md:grid-cols-2 lg:grid-cols-3", children: displayCoupons.map((coupon) => (_jsx(CouponCard, { coupon: coupon, labels: {
99
99
  copy: "Copy",
100
100
  copied: "Copied!",
101
101
  expires: "Expires",
102
102
  minOrder: "Min. order",
103
103
  off: "OFF",
104
104
  freeShipping: "Free Shipping",
105
- } }, coupon.id))) })), totalPages > 1 && (_jsx(Row, { justify: "center", className: "mt-8", children: _jsx(Pagination, { currentPage: table.getNumber("page", 1), totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), !isLoading && total > 0 && (_jsx(Div, { className: "mt-4 text-center", children: _jsxs(Text, { size: "xs", color: "faint", children: [total, " coupon", total !== 1 ? "s" : "", " available"] }) }))] }), _jsxs(ListingFilterDrawer, { open: filterOpen, onClose: () => setFilterOpen(false), onApply: applyFilters, onClear: clearPending, activeCount: activeFilterCount, children: [_jsxs(_Fragment, { children: [_jsx(Heading, { level: 6, className: "tracking-wider mb-3", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: "Discount Type" }), _jsxs(Stack, { gap: "xs", children: [COUPON_TYPES.map((t) => (_jsxs(Label, { layout: "flex", gap: "md", className: "cursor-pointer", color: "primary", size: "sm", children: [_jsx("input", { type: "radio", name: "coupon-type", value: t.value, checked: pendingTable.get(TABLE_KEYS.TYPE) === t.value, onChange: () => { pendingTable.set(TABLE_KEYS.TYPE, t.value); }, className: "accent-primary" }), t.label] }, t.value))), pendingTable.get(TABLE_KEYS.TYPE) && (_jsx("button", { type: "button", onClick: () => { pendingTable.set(TABLE_KEYS.TYPE, ""); }, className: "text-xs text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300 underline", children: "Clear type" }))] })] }), _jsxs(_Fragment, { children: [_jsx(Heading, { level: 6, className: "tracking-wider mb-3", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: "Valid Date Range" }), _jsxs(Stack, { gap: "sm", children: [_jsxs(_Fragment, { children: [_jsx(Label, { className: "block mb-1", color: "muted", size: "xs", children: "From date" }), _jsx("input", { type: "date", value: pendingTable.get(TABLE_KEYS.DATE_FROM) || "", onChange: (e) => { pendingTable.set(TABLE_KEYS.DATE_FROM, e.target.value); }, className: "w-full rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 outline-none focus:ring-2 focus:ring-primary" })] }), _jsxs(_Fragment, { children: [_jsx(Label, { className: "block mb-1", color: "muted", size: "xs", children: "To date" }), _jsx("input", { type: "date", value: pendingTable.get(TABLE_KEYS.DATE_TO) || "", onChange: (e) => { pendingTable.set(TABLE_KEYS.DATE_TO, e.target.value); }, className: "w-full rounded-lg border border-zinc-300 dark:border-slate-600 bg-white dark:bg-slate-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 outline-none focus:ring-2 focus:ring-primary" })] })] })] })] })] }));
105
+ } }, coupon.id))) })), totalPages > 1 && (_jsx(Row, { justify: "center", className: "mt-8", children: _jsx(Pagination, { currentPage: table.getNumber("page", 1), totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), !isLoading && total > 0 && (_jsx(Div, { className: "mt-4 text-center", children: _jsxs(Text, { size: "xs", color: "faint", children: [total, " coupon", total !== 1 ? "s" : "", " available"] }) }))] }), _jsxs(ListingFilterDrawer, { open: filterOpen, onClose: () => setFilterOpen(false), onApply: applyFilters, onClear: clearPending, activeCount: activeFilterCount, children: [_jsxs(_Fragment, { children: [_jsx(Heading, { level: 6, className: "tracking-wider mb-3", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: "Discount Type" }), _jsxs(Stack, { gap: "xs", children: [COUPON_TYPES.map((t) => (_jsxs(Label, { layout: "flex", gap: "md", className: "cursor-pointer", color: "primary", size: "sm", children: [_jsx("input", { type: "radio", name: "coupon-type", value: t.value, checked: pendingTable.get(TABLE_KEYS.TYPE) === t.value, onChange: () => { pendingTable.set(TABLE_KEYS.TYPE, t.value); }, className: "accent-primary" }), t.label] }, t.value))), pendingTable.get(TABLE_KEYS.TYPE) && (_jsx("button", { type: "button", onClick: () => { pendingTable.set(TABLE_KEYS.TYPE, ""); }, className: "text-xs text-zinc-400 hover:text-[var(--appkit-color-text-muted)] hover:text-[var(--appkit-color-text-muted)] underline", children: "Clear type" }))] })] }), _jsxs(_Fragment, { children: [_jsx(Heading, { level: 6, className: "tracking-wider mb-3", color: "muted", size: "xs", weight: "semibold", transform: "uppercase", children: "Valid Date Range" }), _jsxs(Stack, { gap: "sm", children: [_jsxs(_Fragment, { children: [_jsx(Label, { className: "block mb-1", color: "muted", size: "xs", children: "From date" }), _jsx("input", { type: "date", value: pendingTable.get(TABLE_KEYS.DATE_FROM) || "", onChange: (e) => { pendingTable.set(TABLE_KEYS.DATE_FROM, e.target.value); }, className: "w-full rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-3 py-2 text-sm text-[var(--appkit-color-text)] outline-none focus:ring-2 focus:ring-primary" })] }), _jsxs(_Fragment, { children: [_jsx(Label, { className: "block mb-1", color: "muted", size: "xs", children: "To date" }), _jsx("input", { type: "date", value: pendingTable.get(TABLE_KEYS.DATE_TO) || "", onChange: (e) => { pendingTable.set(TABLE_KEYS.DATE_TO, e.target.value); }, className: "w-full rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-3 py-2 text-sm text-[var(--appkit-color-text)] outline-none focus:ring-2 focus:ring-primary" })] })] })] })] })] }));
106
106
  }
@@ -10,7 +10,7 @@ export async function ReviewDetailPageView({ id }) {
10
10
  // storeId === storeSlug for stores in this project (pure slug IDs)
11
11
  const storeSlug = doc?.storeId ?? null;
12
12
  if (!review || review.status !== "approved") {
13
- return (_jsx(Main, { children: _jsx(Section, { padding: "y-6xl", children: _jsx(Container, { size: "sm", children: _jsxs(Div, { className: "text-center", children: [_jsx(Text, { className: "mb-4", size: "5xl", "aria-hidden": "true", children: "\uD83D\uDD0D" }), _jsx(Heading, { color: "inverse", level: 1, className: "text-neutral-900 dark:text-neutral-100 dark: mb-2", size: "2xl", weight: "bold", children: "Review not found" }), _jsx(Text, { className: "text-neutral-500 dark:text-neutral-400 mb-6", size: "sm", children: "This review may have been removed or is no longer available." }), _jsx(Link, { href: String(ROUTES.PUBLIC.REVIEWS), className: "inline-flex items-center gap-2 rounded-lg bg-primary px-5 py-2.5 text-sm font-medium text-white hover:bg-primary-600 transition-colors", children: "\u2190 Back to Reviews" })] }) }) }) }));
13
+ return (_jsx(Main, { children: _jsx(Section, { padding: "y-6xl", children: _jsx(Container, { size: "sm", children: _jsxs(Div, { className: "text-center", children: [_jsx(Text, { className: "mb-4", size: "5xl", "aria-hidden": "true", children: "\uD83D\uDD0D" }), _jsx(Heading, { color: "inverse", level: 1, className: "text-[var(--appkit-color-text)] dark: mb-2", size: "2xl", weight: "bold", children: "Review not found" }), _jsx(Text, { className: "text-[var(--appkit-color-text-muted)] mb-6", size: "sm", children: "This review may have been removed or is no longer available." }), _jsx(Link, { href: String(ROUTES.PUBLIC.REVIEWS), className: "inline-flex items-center gap-2 rounded-lg bg-primary px-5 py-2.5 text-sm font-medium text-white hover:bg-primary-600 transition-colors", children: "\u2190 Back to Reviews" })] }) }) }) }));
14
14
  }
15
15
  return (_jsxs(Main, { children: [_jsx(Div, { paddingY: "y-xs-tall", className: "border-b border-neutral-100 bg-neutral-50", padding: "x-md", children: _jsxs(Nav, { layout: "flex", gap: "2xs", textSize: "xs", color: "faint", className: "mx-auto max-w-3xl", "aria-label": "Breadcrumb", children: [_jsx(Link, { href: String(ROUTES.HOME), className: "hover:text-primary transition-colors", children: "Home" }), _jsx(Span, { children: "/" }), _jsx(Link, { href: String(ROUTES.PUBLIC.REVIEWS), className: "hover:text-primary transition-colors", children: "Reviews" }), _jsx(Span, { children: "/" }), _jsx(Span, { className: "text-neutral-700 truncate max-w-[200px]", children: review.title ?? review.id })] }) }), _jsx(ReviewDetailShell, { review: review, storeHref: storeSlug ? String(ROUTES.PUBLIC.STORE_DETAIL(storeSlug)) : null })] }));
16
16
  }
@@ -7,9 +7,9 @@ const __P = {
7
7
  const __O = {
8
8
  hidden: "overflow-hidden",
9
9
  };
10
- const CLS_RELATED_LINK = "group flex items-center gap-3 rounded-xl border border-neutral-200 dark:border-zinc-700 bg-white dark:bg-zinc-900 p-4 hover:border-primary hover:shadow-sm transition-all";
11
- const CLS_RELATED_LABEL = "text-xs text-zinc-400 dark:text-zinc-400 mb-0.5";
12
- const CLS_RELATED_TITLE = "text-sm font-medium text-neutral-900 dark:text-neutral-100 dark:text-white truncate group-hover:text-primary transition-colors";
10
+ const CLS_RELATED_LINK = "group flex items-center gap-3 rounded-xl border border-neutral-200 border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] p-4 hover:border-primary hover:shadow-sm transition-all";
11
+ const CLS_RELATED_LABEL = "text-xs text-[var(--appkit-color-text-faint)] mb-0.5";
12
+ const CLS_RELATED_TITLE = "text-sm font-medium text-[var(--appkit-color-text)] dark:text-white truncate group-hover:text-primary transition-colors";
13
13
  const CLS_RATING_PILL = "inline-flex items-center gap-1 rounded-full bg-warning-surface px-3 py-1 text-warning dark:bg-warning-surface dark:text-warning";
14
14
  const CLS_HELPFUL_ACTIVE = "border-success bg-success-surface text-success dark:border-success cursor-default";
15
15
  const CLS_ICON_ORANGE = "flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg bg-warning-surface dark:bg-warning-surface text-xl";
@@ -89,9 +89,9 @@ export function ReviewDetailShell({ review, storeHref }) {
89
89
  ? String(ROUTES.PUBLIC.PROFILE(reviewerProfileId))
90
90
  : null;
91
91
  const currentImage = lightboxIdx !== null ? images[lightboxIdx] : null;
92
- return (_jsxs(_Fragment, { children: [_jsx(Div, { surface: "default", className: "border-b border-neutral-200 pt-[2.5rem]", padding: "b-xl", children: _jsxs(Div, { className: "mx-auto max-w-3xl", padding: "x-md", children: [_jsxs(Row, { gap: "sm", className: "mb-4", children: [_jsx(StarRating, { value: review.rating, size: "lg", readOnly: true }), _jsxs(Span, { color: "inverse", weight: "bold", className: "text-neutral-900 dark:text-neutral-100 dark:", size: "2xl", children: [review.rating, ".0"] }), review.verified && (_jsx(Span, { layout: "inline-flex", gap: "xs", color: "success", surface: "success-surface", size: "xs", weight: "semibold", rounded: "full", padding: "pill-md", children: "\u2713 Verified Purchase" })), review.featured && (_jsx(Span, { size: "xs", weight: "semibold", className: CLS_RATING_PILL, children: "\u2605 Featured" }))] }), review.title && (_jsx(Heading, { color: "inverse", level: 1, className: "text-neutral-900 dark:text-neutral-100 dark: mb-4 leading-snug", size: "2xl", weight: "bold", children: review.title })), _jsxs(Row, { gap: "sm", children: [review.userAvatar ? (_jsx("img", { src: review.userAvatar, alt: displayName, className: "h-11 w-11 flex-shrink-0 object-cover rounded-full ring-2 ring-white dark:ring-zinc-800" })) : (_jsx(Row, { textWeight: "bold", textSize: "base", centered: true, className: "h-11 w-11 flex-shrink-0 bg-primary/10 text-primary ring-2 ring-white dark:ring-zinc-800", rounded: "full", children: initials })), _jsxs(Div, { className: "min-w-0", children: [reviewerHref ? (_jsx(Link, { href: reviewerHref, className: "text-sm font-semibold text-neutral-900 dark:text-neutral-100 dark:text-white hover:text-primary transition-colors", children: displayName })) : (_jsx(Span, { color: "inverse", size: "sm", weight: "semibold", className: "text-neutral-900 dark:text-neutral-100 dark:", children: review.isAnonymous ? "Anonymous" : displayName })), date && (_jsx(Text, { size: "xs", color: "muted", className: "mt-0.5", children: date }))] })] })] }) }), _jsxs(Stack, { gap: "xl", className: "mx-auto max-w-3xl", paddingY: "y-xl", paddingX: "x-md", children: [review.comment && (_jsx(Section, { children: _jsx(RichText, { html: normalizeRichTextHtml(review.comment), proseClass: "prose prose-neutral dark:prose-invert max-w-none prose-p:leading-relaxed prose-headings:font-semibold prose-img:rounded-lg prose-a:text-primary", className: "text-neutral-700 dark:text-zinc-300" }) })), images.length > 0 && (_jsxs(Section, { children: [_jsxs(Heading, { level: 2, className: "tracking-wide mb-3", color: "faint", size: "sm", weight: "semibold", transform: "uppercase", children: ["Photos (", images.length, ")"] }), _jsx(Grid, { gap: "xs", className: "grid-cols-3 sm:grid-cols-4", children: images.map((img, i) => (_jsxs("button", { type: "button", onClick: () => setLightboxIdx(i), "aria-label": `View photo ${i + 1}`, className: "group relative aspect-square overflow-hidden rounded-xl border border-neutral-200 dark:border-zinc-700 bg-neutral-100 dark:bg-zinc-800 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary", children: [_jsx("img", { src: img.thumbnailUrl ?? img.url, alt: `Review image ${i + 1}`, className: "h-full w-full object-cover transition-transform duration-300 group-hover:scale-105" }), _jsx(Row, { centered: true, className: "absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity bg-[rgba(0,0,0,0.3)]", children: _jsx(Span, { color: "inverse", size: "xl", children: "\uD83D\uDD0D" }) })] }, i))) })] })), review.video && (_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "tracking-wide mb-3", color: "faint", size: "sm", weight: "semibold", transform: "uppercase", children: "Video" }), _jsx(Div, { className: `${__O.hidden} border border-neutral-200 dark:border-neutral-700 bg-[rgb(0,0,0)] aspect-video`, rounded: "xl", children: _jsx("video", { src: review.video.url, poster: review.video.thumbnailUrl, controls: true, className: "h-full w-full", preload: "metadata" }) })] })), _jsxs(Section, { className: "flex items-[center] gap-[1rem] border-t border-neutral-100", padding: "y-md", children: [_jsx(Div, { textSize: "sm", className: "text-neutral-500 dark:text-neutral-400", children: helpfulCount > 0 && (_jsxs(Span, { children: [_jsx(Span, { color: "inverse", weight: "bold", className: "text-neutral-900 dark:text-neutral-100 dark:", children: helpfulCount }), " ", helpfulCount === 1 ? "person" : "people", " found this helpful"] })) }), _jsxs("button", { type: "button", onClick: handleVote, disabled: voted || voting, className: `ml-auto flex items-center gap-2 rounded-lg border px-4 py-2 text-sm font-medium transition-colors ${voted
92
+ return (_jsxs(_Fragment, { children: [_jsx(Div, { surface: "default", className: "border-b border-neutral-200 pt-[2.5rem]", padding: "b-xl", children: _jsxs(Div, { className: "mx-auto max-w-3xl", padding: "x-md", children: [_jsxs(Row, { gap: "sm", className: "mb-4", children: [_jsx(StarRating, { value: review.rating, size: "lg", readOnly: true }), _jsxs(Span, { color: "inverse", weight: "bold", className: "text-[var(--appkit-color-text)] dark:", size: "2xl", children: [review.rating, ".0"] }), review.verified && (_jsx(Span, { layout: "inline-flex", gap: "xs", color: "success", surface: "success-surface", size: "xs", weight: "semibold", rounded: "full", padding: "pill-md", children: "\u2713 Verified Purchase" })), review.featured && (_jsx(Span, { size: "xs", weight: "semibold", className: CLS_RATING_PILL, children: "\u2605 Featured" }))] }), review.title && (_jsx(Heading, { color: "inverse", level: 1, className: "text-[var(--appkit-color-text)] dark: mb-4 leading-snug", size: "2xl", weight: "bold", children: review.title })), _jsxs(Row, { gap: "sm", children: [review.userAvatar ? (_jsx("img", { src: review.userAvatar, alt: displayName, className: "h-11 w-11 flex-shrink-0 object-cover rounded-full ring-2 ring-white ring-[var(--appkit-color-border-subtle)]" })) : (_jsx(Row, { textWeight: "bold", textSize: "base", centered: true, className: "h-11 w-11 flex-shrink-0 bg-primary/10 text-primary ring-2 ring-white ring-[var(--appkit-color-border-subtle)]", rounded: "full", children: initials })), _jsxs(Div, { className: "min-w-0", children: [reviewerHref ? (_jsx(Link, { href: reviewerHref, className: "text-sm font-semibold text-[var(--appkit-color-text)] dark:text-white hover:text-primary transition-colors", children: displayName })) : (_jsx(Span, { color: "inverse", size: "sm", weight: "semibold", className: "text-[var(--appkit-color-text)] dark:", children: review.isAnonymous ? "Anonymous" : displayName })), date && (_jsx(Text, { size: "xs", color: "muted", className: "mt-0.5", children: date }))] })] })] }) }), _jsxs(Stack, { gap: "xl", className: "mx-auto max-w-3xl", paddingY: "y-xl", paddingX: "x-md", children: [review.comment && (_jsx(Section, { children: _jsx(RichText, { html: normalizeRichTextHtml(review.comment), proseClass: "prose prose-neutral dark:prose-invert max-w-none prose-p:leading-relaxed prose-headings:font-semibold prose-img:rounded-lg prose-a:text-primary", className: "text-neutral-700 text-[var(--appkit-color-text-muted)]" }) })), images.length > 0 && (_jsxs(Section, { children: [_jsxs(Heading, { level: 2, className: "tracking-wide mb-3", color: "faint", size: "sm", weight: "semibold", transform: "uppercase", children: ["Photos (", images.length, ")"] }), _jsx(Grid, { gap: "xs", className: "grid-cols-3 sm:grid-cols-4", children: images.map((img, i) => (_jsxs("button", { type: "button", onClick: () => setLightboxIdx(i), "aria-label": `View photo ${i + 1}`, className: "group relative aspect-square overflow-hidden rounded-xl border border-neutral-200 border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] bg-[var(--appkit-color-surface-elevated)] focus:outline-none focus-visible:ring-2 focus-visible:ring-primary", children: [_jsx("img", { src: img.thumbnailUrl ?? img.url, alt: `Review image ${i + 1}`, className: "h-full w-full object-cover transition-transform duration-300 group-hover:scale-105" }), _jsx(Row, { centered: true, className: "absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity bg-[rgba(0,0,0,0.3)]", children: _jsx(Span, { color: "inverse", size: "xl", children: "\uD83D\uDD0D" }) })] }, i))) })] })), review.video && (_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "tracking-wide mb-3", color: "faint", size: "sm", weight: "semibold", transform: "uppercase", children: "Video" }), _jsx(Div, { className: `${__O.hidden} border border-[var(--appkit-color-border)] bg-[rgb(0,0,0)] aspect-video`, rounded: "xl", children: _jsx("video", { src: review.video.url, poster: review.video.thumbnailUrl, controls: true, className: "h-full w-full", preload: "metadata" }) })] })), _jsxs(Section, { className: "flex items-[center] gap-[1rem] border-t border-neutral-100", padding: "y-md", children: [_jsx(Div, { textSize: "sm", className: "text-[var(--appkit-color-text-muted)]", children: helpfulCount > 0 && (_jsxs(Span, { children: [_jsx(Span, { color: "inverse", weight: "bold", className: "text-[var(--appkit-color-text)] dark:", children: helpfulCount }), " ", helpfulCount === 1 ? "person" : "people", " found this helpful"] })) }), _jsxs("button", { type: "button", onClick: handleVote, disabled: voted || voting, className: `ml-auto flex items-center gap-2 rounded-lg border px-4 py-2 text-sm font-medium transition-colors ${voted
93
93
  ? CLS_HELPFUL_ACTIVE
94
- : "border-neutral-300 dark:border-zinc-600 text-neutral-700 dark:text-zinc-200 hover:border-primary hover:text-primary dark:hover:border-primary dark:hover:text-primary disabled:opacity-50"}`, children: [_jsx(Span, { "aria-hidden": "true", children: voted ? "✓" : "👍" }), voted ? "Marked helpful" : voting ? "Saving…" : "Helpful?"] })] }), _jsxs(Section, { className: "grid gap-[0.75rem] sm:grid-cols-3", children: [productHref && (_jsxs(Link, { href: productHref, className: CLS_RELATED_LINK, children: [_jsx(Span, { className: CLS_ICON_ORANGE, children: "\uD83D\uDCE6" }), _jsxs(Div, { className: "min-w-0", children: [_jsx(Text, { className: CLS_RELATED_LABEL, children: "Product" }), _jsx(Text, { className: CLS_RELATED_TITLE, children: review.productTitle ?? "View Product" })] })] })), sellerHref && (_jsxs(Link, { href: sellerHref, className: CLS_RELATED_LINK, children: [_jsx(Span, { className: CLS_ICON_BLUE, children: "\uD83C\uDFEA" }), _jsxs(Div, { className: "min-w-0", children: [_jsx(Text, { className: CLS_RELATED_LABEL, children: "Seller" }), _jsx(Text, { className: CLS_RELATED_TITLE, children: "View Seller" })] })] })), reviewerHref ? (_jsxs(Link, { href: reviewerHref, className: CLS_RELATED_LINK, children: [_jsx(Span, { className: CLS_ICON_PURPLE, children: "\uD83D\uDC64" }), _jsxs(Div, { className: "min-w-0", children: [_jsx(Text, { className: CLS_RELATED_LABEL, children: "Reviewer" }), _jsx(Text, { className: CLS_RELATED_TITLE, children: displayName })] })] })) : (_jsxs(Row, { surface: "default", gap: "sm", className: `border border-neutral-200 dark:border-[var(--appkit-color-border)] ${__P.p4}`, rounded: "xl", children: [_jsx(Span, { size: "xl", className: CLS_ICON_PURPLE_BARE, children: "\uD83D\uDC64" }), _jsxs(Div, { className: "min-w-0", children: [_jsx(Span, { size: "xs", className: "block mb-0.5", color: "faint", children: "Reviewer" }), _jsx(Span, { color: "inverse", size: "sm", weight: "medium", className: "block text-neutral-900 dark:text-neutral-100 dark: truncate", children: "Anonymous" })] })] }))] })] }), lightboxIdx !== null && currentImage && (_jsxs(Row, { centered: true, className: "fixed inset-0 z-50 bg-[rgba(0,0,0,0.95)]", onClick: closeLightbox, role: "dialog", "aria-modal": "true", "aria-label": "Image lightbox", children: [_jsx("button", { type: "button", onClick: closeLightbox, "aria-label": "Close lightbox", className: "absolute top-4 right-4 z-10 flex h-10 w-10 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/20 transition-colors text-xl", children: "\u00D7" }), _jsxs(Div, { textSize: "sm", className: "absolute top-4 left-1/2 -translate-x-1/2 text-white/70", children: [lightboxIdx + 1, " / ", images.length] }), images.length > 1 && (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); prevImage(); }, "aria-label": "Previous image", className: "absolute left-4 top-1/2 -translate-y-1/2 z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/25 transition-colors text-2xl", children: "\u2039" })), _jsx(Row, { centered: true, className: "max-h-[85vh] max-w-[85vw]", onClick: (e) => e.stopPropagation(), children: _jsx("img", { src: currentImage.url, alt: `Review photo ${lightboxIdx + 1}`, className: "max-h-[85vh] max-w-[85vw] rounded-lg object-contain shadow-2xl" }) }), images.length > 1 && (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); nextImage(); }, "aria-label": "Next image", className: "absolute right-4 top-1/2 -translate-y-1/2 z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/25 transition-colors text-2xl", children: "\u203A" })), images.length > 1 && (_jsx(Row, { justify: "center", gap: "xs", className: "absolute bottom-4 left-0 right-0", padding: "x-md", children: images.map((img, i) => (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); setLightboxIdx(i); }, "aria-label": `Go to image ${i + 1}`, className: `h-12 w-12 flex-shrink-0 rounded-md overflow-hidden border-2 transition-all ${i === lightboxIdx
94
+ : "border-neutral-300 border-[var(--appkit-color-border)] text-neutral-700 text-[var(--appkit-color-text-muted)] hover:border-primary hover:text-primary dark:hover:border-primary dark:hover:text-primary disabled:opacity-50"}`, children: [_jsx(Span, { "aria-hidden": "true", children: voted ? "✓" : "👍" }), voted ? "Marked helpful" : voting ? "Saving…" : "Helpful?"] })] }), _jsxs(Section, { className: "grid gap-[0.75rem] sm:grid-cols-3", children: [productHref && (_jsxs(Link, { href: productHref, className: CLS_RELATED_LINK, children: [_jsx(Span, { className: CLS_ICON_ORANGE, children: "\uD83D\uDCE6" }), _jsxs(Div, { className: "min-w-0", children: [_jsx(Text, { className: CLS_RELATED_LABEL, children: "Product" }), _jsx(Text, { className: CLS_RELATED_TITLE, children: review.productTitle ?? "View Product" })] })] })), sellerHref && (_jsxs(Link, { href: sellerHref, className: CLS_RELATED_LINK, children: [_jsx(Span, { className: CLS_ICON_BLUE, children: "\uD83C\uDFEA" }), _jsxs(Div, { className: "min-w-0", children: [_jsx(Text, { className: CLS_RELATED_LABEL, children: "Seller" }), _jsx(Text, { className: CLS_RELATED_TITLE, children: "View Seller" })] })] })), reviewerHref ? (_jsxs(Link, { href: reviewerHref, className: CLS_RELATED_LINK, children: [_jsx(Span, { className: CLS_ICON_PURPLE, children: "\uD83D\uDC64" }), _jsxs(Div, { className: "min-w-0", children: [_jsx(Text, { className: CLS_RELATED_LABEL, children: "Reviewer" }), _jsx(Text, { className: CLS_RELATED_TITLE, children: displayName })] })] })) : (_jsxs(Row, { surface: "default", gap: "sm", className: `border border-neutral-200 dark:border-[var(--appkit-color-border)] ${__P.p4}`, rounded: "xl", children: [_jsx(Span, { size: "xl", className: CLS_ICON_PURPLE_BARE, children: "\uD83D\uDC64" }), _jsxs(Div, { className: "min-w-0", children: [_jsx(Span, { size: "xs", className: "block mb-0.5", color: "faint", children: "Reviewer" }), _jsx(Span, { color: "inverse", size: "sm", weight: "medium", className: "block text-[var(--appkit-color-text)] dark: truncate", children: "Anonymous" })] })] }))] })] }), lightboxIdx !== null && currentImage && (_jsxs(Row, { centered: true, className: "fixed inset-0 z-50 bg-[rgba(0,0,0,0.95)]", onClick: closeLightbox, role: "dialog", "aria-modal": "true", "aria-label": "Image lightbox", children: [_jsx("button", { type: "button", onClick: closeLightbox, "aria-label": "Close lightbox", className: "absolute top-4 right-4 z-10 flex h-10 w-10 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/20 transition-colors text-xl", children: "\u00D7" }), _jsxs(Div, { textSize: "sm", className: "absolute top-4 left-1/2 -translate-x-1/2 text-white/70", children: [lightboxIdx + 1, " / ", images.length] }), images.length > 1 && (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); prevImage(); }, "aria-label": "Previous image", className: "absolute left-4 top-1/2 -translate-y-1/2 z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/25 transition-colors text-2xl", children: "\u2039" })), _jsx(Row, { centered: true, className: "max-h-[85vh] max-w-[85vw]", onClick: (e) => e.stopPropagation(), children: _jsx("img", { src: currentImage.url, alt: `Review photo ${lightboxIdx + 1}`, className: "max-h-[85vh] max-w-[85vw] rounded-lg object-contain shadow-2xl" }) }), images.length > 1 && (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); nextImage(); }, "aria-label": "Next image", className: "absolute right-4 top-1/2 -translate-y-1/2 z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/25 transition-colors text-2xl", children: "\u203A" })), images.length > 1 && (_jsx(Row, { justify: "center", gap: "xs", className: "absolute bottom-4 left-0 right-0", padding: "x-md", children: images.map((img, i) => (_jsx("button", { type: "button", onClick: (e) => { e.stopPropagation(); setLightboxIdx(i); }, "aria-label": `Go to image ${i + 1}`, className: `h-12 w-12 flex-shrink-0 rounded-md overflow-hidden border-2 transition-all ${i === lightboxIdx
95
95
  ? "border-white scale-110"
96
96
  : "border-transparent opacity-60 hover:opacity-100"}`, children: _jsx("img", { src: img.thumbnailUrl ?? img.url, alt: `Thumbnail ${i + 1}`, className: "w-full h-full object-cover" }) }, i))) }))] }))] }));
97
97
  }
@@ -23,5 +23,5 @@ export function ViewReviewModal({ review, isOpen, onClose, }) {
23
23
  day: "numeric",
24
24
  })
25
25
  : "";
26
- return (_jsx(Modal, { isOpen: isOpen, onClose: onClose, title: "Review Details", children: _jsxs(Stack, { gap: "md", children: [_jsxs(Row, { gap: "3", children: [review.userAvatar ? (_jsx("img", { src: review.userAvatar, alt: displayName, className: "h-10 w-10 flex-shrink-0 object-cover rounded-full" })) : (_jsx(Row, { textWeight: "medium", textSize: "sm", className: "h-10 w-10 flex-shrink-0 bg-neutral-200 text-neutral-600 dark:text-neutral-400", align: "center", justify: "center", rounded: "full", children: displayName.charAt(0).toUpperCase() })), _jsxs(Div, { children: [_jsxs(Row, { gap: "sm", children: [_jsx(Text, { color: "inverse", className: "text-neutral-900 dark:text-neutral-100 dark:", weight: "medium", children: displayName }), review.verified && (_jsx(Text, { className: THEMED_TEXT_SUCCESS, size: "xs", children: "\u2713 Verified purchase" }))] }), _jsxs(Row, { className: "mt-0.5", gap: "sm", children: [_jsx(StarRating, { value: review.rating, size: "sm", readOnly: true }), date && (_jsx(Text, { size: "xs", color: "faint", children: date }))] })] })] }), review.title && (_jsx(Heading, { color: "inverse", level: 4, className: "text-neutral-900 dark:text-neutral-100 dark:", weight: "semibold", children: review.title })), review.comment && (_jsx(RichText, { html: normalizeRichTextHtml(review.comment), proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-sm leading-relaxed text-neutral-600 dark:text-zinc-400" })), review.images && review.images.length > 0 && (_jsx(Row, { wrap: true, gap: "sm", children: review.images.map((img, i) => (_jsx("button", { type: "button", "aria-label": `View image ${i + 1}`, onClick: () => setLightboxIdx(i), className: `h-20 w-20 rounded-lg border overflow-hidden transition hover:opacity-80 p-0 flex-shrink-0 ${lightboxIdx === i ? "ring-2 ring-primary-500" : "border-neutral-100 dark:border-zinc-700"}`, children: _jsx("img", { src: img.thumbnailUrl ?? img.url, alt: `Review thumbnail ${i + 1}`, className: "w-full h-full object-cover" }) }, i))) })), (review.helpfulCount ?? 0) > 0 && (_jsxs(Text, { size: "xs", color: "faint", children: [review.helpfulCount, " people found this helpful"] })), _jsx(Row, { justify: "end", padding: "t-xs", children: _jsx(Button, { variant: "ghost", onClick: onClose, children: "Close" }) })] }) }));
26
+ return (_jsx(Modal, { isOpen: isOpen, onClose: onClose, title: "Review Details", children: _jsxs(Stack, { gap: "md", children: [_jsxs(Row, { gap: "3", children: [review.userAvatar ? (_jsx("img", { src: review.userAvatar, alt: displayName, className: "h-10 w-10 flex-shrink-0 object-cover rounded-full" })) : (_jsx(Row, { textWeight: "medium", textSize: "sm", className: "h-10 w-10 flex-shrink-0 bg-neutral-200 text-[var(--appkit-color-text-muted)]", align: "center", justify: "center", rounded: "full", children: displayName.charAt(0).toUpperCase() })), _jsxs(Div, { children: [_jsxs(Row, { gap: "sm", children: [_jsx(Text, { color: "inverse", className: "text-[var(--appkit-color-text)] dark:", weight: "medium", children: displayName }), review.verified && (_jsx(Text, { className: THEMED_TEXT_SUCCESS, size: "xs", children: "\u2713 Verified purchase" }))] }), _jsxs(Row, { className: "mt-0.5", gap: "sm", children: [_jsx(StarRating, { value: review.rating, size: "sm", readOnly: true }), date && (_jsx(Text, { size: "xs", color: "faint", children: date }))] })] })] }), review.title && (_jsx(Heading, { color: "inverse", level: 4, className: "text-[var(--appkit-color-text)] dark:", weight: "semibold", children: review.title })), review.comment && (_jsx(RichText, { html: normalizeRichTextHtml(review.comment), proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "text-sm leading-relaxed text-[var(--appkit-color-text-muted)] text-[var(--appkit-color-text-muted)]" })), review.images && review.images.length > 0 && (_jsx(Row, { wrap: true, gap: "sm", children: review.images.map((img, i) => (_jsx("button", { type: "button", "aria-label": `View image ${i + 1}`, onClick: () => setLightboxIdx(i), className: `h-20 w-20 rounded-lg border overflow-hidden transition hover:opacity-80 p-0 flex-shrink-0 ${lightboxIdx === i ? "ring-2 ring-primary-500" : "border-neutral-100 border-[var(--appkit-color-border)]"}`, children: _jsx("img", { src: img.thumbnailUrl ?? img.url, alt: `Review thumbnail ${i + 1}`, className: "w-full h-full object-cover" }) }, i))) })), (review.helpfulCount ?? 0) > 0 && (_jsxs(Text, { size: "xs", color: "faint", children: [review.helpfulCount, " people found this helpful"] })), _jsx(Row, { justify: "end", padding: "t-xs", children: _jsx(Button, { variant: "ghost", onClick: onClose, children: "Close" }) })] }) }));
27
27
  }
@@ -14,9 +14,9 @@ const CLS_BAR = "h-full rounded-full bg-warning-surface transition-all duration-
14
14
  */
15
15
  export function ReviewSummary({ averageRating, totalReviews, distribution, className = "", }) {
16
16
  const stars = [5, 4, 3, 2, 1];
17
- return (_jsxs(Stack, { align: "center", className: `sm:[flex-direction:row] sm: sm:gap-[2rem] ${className}`, gap: "md", children: [_jsxs(Stack, { className: "sm:items-[flex-start]", align: "center", gap: "xs", children: [_jsx(Span, { color: "inverse", weight: "bold", className: "leading-none text-neutral-900 dark:text-neutral-100 dark:", size: "5xl", children: averageRating.toFixed(1) }), _jsx(StarRating, { value: averageRating, size: "md", readOnly: true }), _jsxs(Text, { size: "sm", className: "text-neutral-500 dark:text-neutral-400", children: [totalReviews.toLocaleString(), " review", totalReviews !== 1 ? "s" : ""] })] }), _jsx(Stack, { className: "flex-1", gap: "sm", children: stars.map((star) => {
17
+ return (_jsxs(Stack, { align: "center", className: `sm:[flex-direction:row] sm: sm:gap-[2rem] ${className}`, gap: "md", children: [_jsxs(Stack, { className: "sm:items-[flex-start]", align: "center", gap: "xs", children: [_jsx(Span, { color: "inverse", weight: "bold", className: "leading-none text-[var(--appkit-color-text)] dark:", size: "5xl", children: averageRating.toFixed(1) }), _jsx(StarRating, { value: averageRating, size: "md", readOnly: true }), _jsxs(Text, { size: "sm", className: "text-[var(--appkit-color-text-muted)]", children: [totalReviews.toLocaleString(), " review", totalReviews !== 1 ? "s" : ""] })] }), _jsx(Stack, { className: "flex-1", gap: "sm", children: stars.map((star) => {
18
18
  const count = distribution[star] ?? 0;
19
19
  const pct = totalReviews > 0 ? Math.round((count / totalReviews) * 100) : 0;
20
- return (_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Span, { size: "xs", weight: "medium", className: "w-4 text-neutral-600 dark:text-neutral-400 tabular-nums", align: "end", children: star }), _jsx(Span, { size: "xs", className: CLS_STAR, children: "\u2605" }), _jsx(Div, { className: "flex-1 h-2 bg-neutral-100 dark:bg-neutral-800 overflow-hidden", rounded: "full", role: "progressbar", "aria-valuenow": pct, "aria-valuemin": 0, "aria-valuemax": 100, "aria-label": `${star} star: ${pct}%`, children: _jsx(ProgressBarFill, { pct: pct, className: CLS_BAR }) }), _jsxs(Span, { size: "xs", className: "w-8 tabular-nums", color: "faint", align: "end", children: [pct, "%"] })] }, star));
20
+ return (_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Span, { size: "xs", weight: "medium", className: "w-4 text-[var(--appkit-color-text-muted)] tabular-nums", align: "end", children: star }), _jsx(Span, { size: "xs", className: CLS_STAR, children: "\u2605" }), _jsx(Div, { className: "flex-1 h-2 bg-[var(--appkit-color-surface)] overflow-hidden", rounded: "full", role: "progressbar", "aria-valuenow": pct, "aria-valuemin": 0, "aria-valuemax": 100, "aria-label": `${star} star: ${pct}%`, children: _jsx(ProgressBarFill, { pct: pct, className: CLS_BAR }) }), _jsxs(Span, { size: "xs", className: "w-8 tabular-nums", color: "faint", align: "end", children: [pct, "%"] })] }, star));
21
21
  }) })] }));
22
22
  }
@@ -108,5 +108,5 @@ export function ReviewsIndexListing({ initialData, variant = "public", }) {
108
108
  value: opt.value,
109
109
  label: SORT_OPTION_LABELS[opt.key] ?? opt.key,
110
110
  }));
111
- return (_jsxs(Div, { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search reviews by product name...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: sort, sortOptions: sortOptions, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, view: view, onViewChange: handleViewToggle, onResetAll: resetAll, hasActiveState: hasActiveState }), totalPages > 1 && (_jsx(Row, { border: "bottom", className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 backdrop-blur-sm", surface: "default", padding: "toolbar", justify: "center", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsx(Div, { padding: "y-lg", children: isLoading ? (_jsx(Div, { layout: "grid", gap: "6", className: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsx(Div, { className: `${__O.hidden} animate-pulse`, border: "subtle", rounded: "xl", children: _jsxs(Stack, { className: `${__P.p4}`, gap: "3", children: [_jsx(Div, { className: "h-4 w-3/4", surface: "subtle", rounded: "default" }), _jsx(Div, { className: "h-3 w-full", surface: "subtle", rounded: "default" }), _jsx(Div, { className: "h-3 w-2/3", surface: "subtle", rounded: "default" })] }) }, i))) })) : reviews.length === 0 ? (_jsx(Text, { paddingY: "3xl", color: "muted", size: "sm", align: "center", children: "No reviews found." })) : view === "list" ? (_jsx(Stack, { className: "divide-y divide-zinc-100 dark:divide-zinc-800", border: "subtle", rounded: "xl", children: reviews.map((review) => (_jsx(ReviewCard, { review: review }, review.id))) })) : (_jsx(Div, { layout: "grid", gap: "6", className: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3", children: reviews.map((review) => (_jsx(ReviewCard, { review: review }, review.id))) })) }), _jsx(ListingFilterDrawer, { open: filterOpen, onClose: () => setFilterOpen(false), onApply: applyFilters, onClear: clearFilters, activeCount: activeFilterCount, children: _jsx(ReviewFilters, { table: pendingTable, variant: variant }) })] }));
111
+ return (_jsxs(Div, { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search reviews by product name...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: sort, sortOptions: sortOptions, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, view: view, onViewChange: handleViewToggle, onResetAll: resetAll, hasActiveState: hasActiveState }), totalPages > 1 && (_jsx(Row, { border: "bottom", className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 backdrop-blur-sm", surface: "default", padding: "toolbar", justify: "center", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsx(Div, { padding: "y-lg", children: isLoading ? (_jsx(Div, { layout: "grid", gap: "6", className: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsx(Div, { className: `${__O.hidden} animate-pulse`, border: "subtle", rounded: "xl", children: _jsxs(Stack, { className: `${__P.p4}`, gap: "3", children: [_jsx(Div, { className: "h-4 w-3/4", surface: "subtle", rounded: "default" }), _jsx(Div, { className: "h-3 w-full", surface: "subtle", rounded: "default" }), _jsx(Div, { className: "h-3 w-2/3", surface: "subtle", rounded: "default" })] }) }, i))) })) : reviews.length === 0 ? (_jsx(Text, { paddingY: "3xl", color: "muted", size: "sm", align: "center", children: "No reviews found." })) : view === "list" ? (_jsx(Stack, { className: "divide-y divide-zinc-100 divide-[var(--appkit-color-border-subtle)]", border: "subtle", rounded: "xl", children: reviews.map((review) => (_jsx(ReviewCard, { review: review }, review.id))) })) : (_jsx(Div, { layout: "grid", gap: "6", className: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3", children: reviews.map((review) => (_jsx(ReviewCard, { review: review }, review.id))) })) }), _jsx(ListingFilterDrawer, { open: filterOpen, onClose: () => setFilterOpen(false), onApply: applyFilters, onClear: clearFilters, activeCount: activeFilterCount, children: _jsx(ReviewFilters, { table: pendingTable, variant: variant }) })] }));
112
112
  }
@@ -27,14 +27,14 @@ export function ReviewCard({ review, context = "general", className = "" }) {
27
27
  const showProductLink = context !== "listing" && !!productHref;
28
28
  const showProfileLink = !!profileHref;
29
29
  const hasFooter = showStoreLink || showProductLink || showProfileLink;
30
- return (_jsxs(Stack, { padding: "5", shadow: "hover-md", className: `group h-full border border-neutral-200 transition ${className}`, rounded: "xl", surface: "default", children: [_jsxs(Link, { href: reviewHref, className: "flex flex-col flex-1 min-h-0", children: [_jsxs(Row, { align: "start", gap: "3", children: [review.userAvatar ? (_jsx("img", { src: review.userAvatar, alt: displayName, className: "h-9 w-9 flex-shrink-0 object-cover rounded-full" })) : (_jsx(Row, { textWeight: "medium", textSize: "sm", className: "h-9 w-9 flex-shrink-0 bg-neutral-200 text-neutral-600 dark:text-neutral-400", align: "center", justify: "center", rounded: "full", children: initials })), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsxs(Row, { wrap: true, gap: "sm", children: [_jsx(Span, { color: "inverse", weight: "medium", className: "text-neutral-900 dark:text-neutral-100 dark:", children: displayName }), review.verified && (_jsx(Span, { color: "success", surface: "success-surface", size: "xs", weight: "medium", rounded: "full", padding: "pill-xs", children: "Verified" })), date && (_jsx(Span, { size: "xs", color: "muted", children: date }))] }), _jsx(Div, { className: "mt-1", children: _jsx(StarRating, { value: review.rating, size: "sm", readOnly: true }) })] })] }), review.title && (_jsx(Heading, { color: "inverse", level: 4, className: "mt-3 text-neutral-900 dark:text-neutral-100 dark:", weight: "semibold", children: review.title })), review.comment && (_jsx(RichText, { html: normalizeRichTextHtml(review.comment), proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "mt-2 text-sm leading-relaxed text-neutral-600 dark:text-zinc-400" })), review.images && review.images.length > 0 && (_jsx(Row, { wrap: true, gap: "sm", className: "mt-3", children: review.images.map((img, i) => (_jsx("img", { src: img.thumbnailUrl ?? img.url, alt: `Review image ${i + 1}`, className: "h-16 w-16 object-cover rounded-lg border border-neutral-100" }, i))) })), (review.helpfulCount ?? 0) > 0 && (_jsxs(Text, { className: "mt-3", color: "faint", size: "xs", children: [review.helpfulCount, " found this helpful"] }))] }), hasFooter && (_jsxs(Stack, { gap: "xs", className: "mt-3 border-t border-neutral-100", padding: "t-sm", children: [showStoreLink && (_jsxs(Link, { href: String(ROUTES.PUBLIC.STORE_DETAIL(review.storeSlug)), className: "flex items-center gap-1.5 text-xs font-medium text-primary hover:underline", children: [_jsx(Span, { "aria-hidden": "true", children: "\uD83C\uDFEA" }), _jsx(Span, { truncate: true, children: review.storeName })] })), showProductLink && (_jsxs(Link, { href: productHref, className: "flex items-center gap-1.5 text-xs font-medium text-neutral-500 dark:text-zinc-400 hover:text-neutral-700 dark:hover:text-zinc-200", children: [_jsx(Span, { "aria-hidden": "true", children: "\uD83D\uDCE6" }), _jsx(Span, { truncate: true, children: review.productTitle ?? "View Product" }), _jsx(Span, { "aria-hidden": "true", className: "ml-auto text-primary group-hover:translate-x-0.5 transition-transform", children: "\u2192" })] })), showProfileLink && (_jsxs(Link, { href: profileHref, className: "flex items-center gap-1.5 text-xs font-medium text-neutral-500 dark:text-zinc-400 hover:text-neutral-700 dark:hover:text-zinc-200", children: [_jsx(Span, { "aria-hidden": "true", children: "\uD83D\uDC64" }), _jsx(Span, { truncate: true, children: displayName })] }))] }))] }));
30
+ return (_jsxs(Stack, { padding: "5", shadow: "hover-md", className: `group h-full border border-neutral-200 transition ${className}`, rounded: "xl", surface: "default", children: [_jsxs(Link, { href: reviewHref, className: "flex flex-col flex-1 min-h-0", children: [_jsxs(Row, { align: "start", gap: "3", children: [review.userAvatar ? (_jsx("img", { src: review.userAvatar, alt: displayName, className: "h-9 w-9 flex-shrink-0 object-cover rounded-full" })) : (_jsx(Row, { textWeight: "medium", textSize: "sm", className: "h-9 w-9 flex-shrink-0 bg-neutral-200 text-[var(--appkit-color-text-muted)]", align: "center", justify: "center", rounded: "full", children: initials })), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsxs(Row, { wrap: true, gap: "sm", children: [_jsx(Span, { color: "inverse", weight: "medium", className: "text-[var(--appkit-color-text)] dark:", children: displayName }), review.verified && (_jsx(Span, { color: "success", surface: "success-surface", size: "xs", weight: "medium", rounded: "full", padding: "pill-xs", children: "Verified" })), date && (_jsx(Span, { size: "xs", color: "muted", children: date }))] }), _jsx(Div, { className: "mt-1", children: _jsx(StarRating, { value: review.rating, size: "sm", readOnly: true }) })] })] }), review.title && (_jsx(Heading, { color: "inverse", level: 4, className: "mt-3 text-[var(--appkit-color-text)] dark:", weight: "semibold", children: review.title })), review.comment && (_jsx(RichText, { html: normalizeRichTextHtml(review.comment), proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: "mt-2 text-sm leading-relaxed text-[var(--appkit-color-text-muted)] text-[var(--appkit-color-text-muted)]" })), review.images && review.images.length > 0 && (_jsx(Row, { wrap: true, gap: "sm", className: "mt-3", children: review.images.map((img, i) => (_jsx("img", { src: img.thumbnailUrl ?? img.url, alt: `Review image ${i + 1}`, className: "h-16 w-16 object-cover rounded-lg border border-neutral-100" }, i))) })), (review.helpfulCount ?? 0) > 0 && (_jsxs(Text, { className: "mt-3", color: "faint", size: "xs", children: [review.helpfulCount, " found this helpful"] }))] }), hasFooter && (_jsxs(Stack, { gap: "xs", className: "mt-3 border-t border-neutral-100", padding: "t-sm", children: [showStoreLink && (_jsxs(Link, { href: String(ROUTES.PUBLIC.STORE_DETAIL(review.storeSlug)), className: "flex items-center gap-1.5 text-xs font-medium text-primary hover:underline", children: [_jsx(Span, { "aria-hidden": "true", children: "\uD83C\uDFEA" }), _jsx(Span, { truncate: true, children: review.storeName })] })), showProductLink && (_jsxs(Link, { href: productHref, className: "flex items-center gap-1.5 text-xs font-medium text-[var(--appkit-color-text-muted)] text-[var(--appkit-color-text-muted)] hover:text-neutral-700 hover:text-[var(--appkit-color-text-muted)]", children: [_jsx(Span, { "aria-hidden": "true", children: "\uD83D\uDCE6" }), _jsx(Span, { truncate: true, children: review.productTitle ?? "View Product" }), _jsx(Span, { "aria-hidden": "true", className: "ml-auto text-primary group-hover:translate-x-0.5 transition-transform", children: "\u2192" })] })), showProfileLink && (_jsxs(Link, { href: profileHref, className: "flex items-center gap-1.5 text-xs font-medium text-[var(--appkit-color-text-muted)] text-[var(--appkit-color-text-muted)] hover:text-neutral-700 hover:text-[var(--appkit-color-text-muted)]", children: [_jsx(Span, { "aria-hidden": "true", children: "\uD83D\uDC64" }), _jsx(Span, { truncate: true, children: displayName })] }))] }))] }));
31
31
  }
32
32
  export function ReviewsList({ reviews, context = "general", isLoading, totalPages = 1, currentPage = 1, onPageChange, emptyLabel = "No reviews yet", }) {
33
33
  if (isLoading) {
34
34
  return (_jsx(Stack, { gap: "md", children: Array.from({ length: 4 }).map((_, i) => (_jsxs(Div, { padding: "5", className: "border border-neutral-200", rounded: "xl", children: [_jsxs(Row, { gap: "3", children: [_jsx(Skeleton, { className: "h-9 w-9 rounded-full" }), _jsxs(Stack, { gap: "sm", className: "flex-1", children: [_jsx(Skeleton, { className: "h-4 w-24 rounded" }), _jsx(Skeleton, { className: "h-3 w-16 rounded" })] })] }), _jsxs(Stack, { gap: "xs", className: "mt-3", children: [_jsx(Skeleton, { className: "h-3 w-full rounded" }), _jsx(Skeleton, { className: "h-3 w-3/4 rounded" })] })] }, i))) }));
35
35
  }
36
36
  if (reviews.length === 0) {
37
- return (_jsx(Text, { paddingY: "3xl", className: "text-neutral-500 dark:text-neutral-400", size: "sm", align: "center", children: emptyLabel }));
37
+ return (_jsx(Text, { paddingY: "3xl", className: "text-[var(--appkit-color-text-muted)]", size: "sm", align: "center", children: emptyLabel }));
38
38
  }
39
39
  return (_jsxs(Stack, { gap: "lg", children: [_jsx(Stack, { gap: "md", children: reviews.map((review) => (_jsx(ReviewCard, { review: review, context: context }, review.id))) }), totalPages > 1 && onPageChange && (_jsx(Row, { justify: "center", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: onPageChange }) }))] }));
40
40
  }
@@ -3,7 +3,7 @@ import { Span, sortBy } from "@mohasinac/appkit";
3
3
  import Link from "next/link";
4
4
  import { ROUTES } from "../../../next/routing/route-map";
5
5
  const CLS_ICON_SM = "h-3 w-3 shrink-0";
6
- const CLS_ROW_CHEVRON = "h-4 w-4 shrink-0 text-zinc-300 transition group-hover:text-error dark:text-zinc-600";
6
+ const CLS_ROW_CHEVRON = "h-4 w-4 shrink-0 text-zinc-300 transition group-hover:text-error text-[var(--appkit-color-text-faint)]";
7
7
  const CLS_PILL_LINK = "inline-flex items-center gap-1 rounded-full bg-error-surface dark:bg-error-surface px-2.5 py-0.5 text-xs font-medium text-error dark:text-error hover:bg-error-surface transition-colors";
8
8
  import { Shield, Phone, Wallet, Mail, ChevronRight, Search } from "lucide-react";
9
9
  import { Button, Container, Div, Form, Heading, Main, Section, Select, Text, Grid, Stack, Row, Card, Badge, Alert, EmptyState, Input, } from "../../../ui";
@@ -65,7 +65,7 @@ export async function ScamRegistryView({ searchParams = {} }) {
65
65
  const qs = p.toString();
66
66
  return `/scams${qs ? `?${qs}` : ""}`;
67
67
  }
68
- return (_jsxs(Main, { children: [_jsx(Div, { className: "border-b appkit-alert--warning", rounded: "none", children: _jsx(Container, { padding: "y-xs", size: "xl", className: "", children: _jsxs(Alert, { variant: "warning", compact: true, children: ["All profiles on this page have been verified by our moderation team. If you recognise a scammer not listed here,", " ", _jsx(Link, { href: reportHref, className: "font-medium underline hover:no-underline", children: "report them" }), "."] }) }) }), _jsx(Section, { padding: "y-2xl", children: _jsx(Container, { size: "xl", children: _jsxs(Stack, { gap: "xl", children: [_jsxs(Row, { justify: "between", gap: "md", align: "end", wrap: true, children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 1, weight: "semibold", size: "3xl", children: "Scam Registry" }), _jsx(Text, { variant: "secondary", size: "sm", children: "Verified scammers active in India's collectibles community. Search by name, phone, or UPI." })] }), _jsxs(Link, { href: reportHref, className: "appkit-button appkit-button--danger appkit-button--md shrink-0", children: [_jsx(Shield, { className: "h-4 w-4" }), "Report a Scammer"] })] }), _jsx(Form, { method: "GET", children: _jsxs(Row, { wrap: true, gap: "sm", children: [_jsx(Div, { className: "flex-1 min-w-48", children: _jsx(Input, { type: "search", name: "q", defaultValue: query, placeholder: "Search name, phone, UPI ID, or email\u2026", icon: _jsx(Search, { className: "h-4 w-4" }) }) }), _jsx(Select, { name: "scamType", defaultValue: scamType, options: SCAM_TYPES.map((t) => ({ value: t.id, label: t.label })), placeholder: "All scam types" }), _jsx(Select, { name: "sort", defaultValue: sort, options: SORT_OPTIONS.map((o) => ({ value: o.value, label: o.label })) }), _jsx(Button, { type: "submit", variant: "primary", size: "sm", children: "Search" }), (query || scamType || sort !== "-createdAt") && (_jsx(Link, { href: ROUTES.PUBLIC.SCAMS, className: "rounded-lg border border-zinc-300 dark:border-slate-600 px-4 py-2 text-sm text-zinc-600 dark:text-zinc-400 hover:bg-zinc-50 dark:hover:bg-slate-800 transition-colors", children: "Clear" }))] }) }), scamType && SCAM_TYPE_LABELS[scamType] && (_jsxs(Row, { gap: "sm", align: "center", children: [_jsx(Text, { variant: "secondary", size: "xs", children: "Filtering by:" }), _jsxs(Link, { href: buildHref({ scamType: "" }), className: CLS_PILL_LINK, children: [SCAM_TYPE_LABELS[scamType], _jsx(Span, { "aria-hidden": "true", children: "\u00D7" })] })] })), result.items.length === 0 ? (_jsx(EmptyState, { icon: _jsx(Shield, { className: "h-12 w-12" }), title: query || scamType
68
+ return (_jsxs(Main, { children: [_jsx(Div, { className: "border-b appkit-alert--warning", rounded: "none", children: _jsx(Container, { padding: "y-xs", size: "xl", className: "", children: _jsxs(Alert, { variant: "warning", compact: true, children: ["All profiles on this page have been verified by our moderation team. If you recognise a scammer not listed here,", " ", _jsx(Link, { href: reportHref, className: "font-medium underline hover:no-underline", children: "report them" }), "."] }) }) }), _jsx(Section, { padding: "y-2xl", children: _jsx(Container, { size: "xl", children: _jsxs(Stack, { gap: "xl", children: [_jsxs(Row, { justify: "between", gap: "md", align: "end", wrap: true, children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 1, weight: "semibold", size: "3xl", children: "Scam Registry" }), _jsx(Text, { variant: "secondary", size: "sm", children: "Verified scammers active in India's collectibles community. Search by name, phone, or UPI." })] }), _jsxs(Link, { href: reportHref, className: "appkit-button appkit-button--danger appkit-button--md shrink-0", children: [_jsx(Shield, { className: "h-4 w-4" }), "Report a Scammer"] })] }), _jsx(Form, { method: "GET", children: _jsxs(Row, { wrap: true, gap: "sm", children: [_jsx(Div, { className: "flex-1 min-w-48", children: _jsx(Input, { type: "search", name: "q", defaultValue: query, placeholder: "Search name, phone, UPI ID, or email\u2026", icon: _jsx(Search, { className: "h-4 w-4" }) }) }), _jsx(Select, { name: "scamType", defaultValue: scamType, options: SCAM_TYPES.map((t) => ({ value: t.id, label: t.label })), placeholder: "All scam types" }), _jsx(Select, { name: "sort", defaultValue: sort, options: SORT_OPTIONS.map((o) => ({ value: o.value, label: o.label })) }), _jsx(Button, { type: "submit", variant: "primary", size: "sm", children: "Search" }), (query || scamType || sort !== "-createdAt") && (_jsx(Link, { href: ROUTES.PUBLIC.SCAMS, className: "rounded-lg border border-[var(--appkit-color-border)] px-4 py-2 text-sm text-[var(--appkit-color-text-muted)] hover:bg-zinc-50 hover:bg-[var(--appkit-color-surface-elevated)] transition-colors", children: "Clear" }))] }) }), scamType && SCAM_TYPE_LABELS[scamType] && (_jsxs(Row, { gap: "sm", align: "center", children: [_jsx(Text, { variant: "secondary", size: "xs", children: "Filtering by:" }), _jsxs(Link, { href: buildHref({ scamType: "" }), className: CLS_PILL_LINK, children: [SCAM_TYPE_LABELS[scamType], _jsx(Span, { "aria-hidden": "true", children: "\u00D7" })] })] })), result.items.length === 0 ? (_jsx(EmptyState, { icon: _jsx(Shield, { className: "h-12 w-12" }), title: query || scamType
69
69
  ? "No verified scammers matched your filters"
70
70
  : "No verified scammers in the registry yet", description: query || scamType
71
71
  ? "Try a different search or clear your filters."
@@ -5,8 +5,8 @@ const __O = {
5
5
  hidden: "overflow-hidden",
6
6
  };
7
7
  const SVG_PATH_SEARCH = "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z";
8
- const CLS_HOVER_ROW = "hover:bg-zinc-100 dark:hover:bg-slate-800";
9
- const CLS_ICON_ROW = "w-4 h-4 flex-shrink-0 text-zinc-500 dark:text-zinc-400";
8
+ const CLS_HOVER_ROW = "hover:bg-[var(--appkit-color-surface)] hover:bg-[var(--appkit-color-surface-elevated)]";
9
+ const CLS_ICON_ROW = "w-4 h-4 flex-shrink-0 text-[var(--appkit-color-text-muted)]";
10
10
  const CLS_TRUNCATE = "font-medium truncate";
11
11
  import { Button, Div, Input, Li, Row, Span, Stack, Text, Ul } from "../../../ui";
12
12
  import { useNavSuggestions } from "../hooks/useNavSuggestions";
@@ -18,7 +18,7 @@ const DEFAULT_TYPE_ICONS = {
18
18
  product: "📦",
19
19
  };
20
20
  const DEFAULT_TYPE_BADGES = {
21
- page: "bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300",
21
+ page: "bg-[var(--appkit-color-surface)] text-[var(--appkit-color-text-muted)] bg-[var(--appkit-color-surface-elevated)] text-[var(--appkit-color-text-muted)]",
22
22
  category: "bg-info-surface text-info dark:bg-info-surface dark:text-info",
23
23
  blog: "bg-fuchsia-100 text-fuchsia-600 dark:bg-fuchsia-900/40 dark:text-fuchsia-300",
24
24
  event: "bg-warning-surface text-warning dark:bg-warning-surface dark:text-warning",
@@ -26,7 +26,7 @@ const DEFAULT_TYPE_BADGES = {
26
26
  };
27
27
  function SuggestionItem({ suggestion, itemIndex, activeIndex, onSelect, onHover, typeIcons, typeBadges, }) {
28
28
  const isActive = activeIndex === itemIndex;
29
- return (_jsx(Li, { children: _jsxs(Button, { type: "button", variant: "ghost", onClick: () => onSelect(suggestion), onMouseEnter: () => onHover(itemIndex), className: `w-full flex items-center gap-3 px-4 py-3 text-left transition-colors border-b border-zinc-200 dark:border-slate-700 last:border-b-0 ${isActive ? "bg-zinc-100 dark:bg-slate-800" : CLS_HOVER_ROW}`, children: [_jsx(Span, { size: "sm", children: typeIcons[suggestion.type] }), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Text, { size: "sm", className: CLS_TRUNCATE, children: suggestion.title }), suggestion.subtitle && (_jsx(Text, { variant: "secondary", size: "xs", className: "truncate", children: suggestion.subtitle }))] }), _jsx(Span, { size: "xs", className: `${typeBadges[suggestion.type]}`, rounded: "full", padding: "pill-xs", children: suggestion.type })] }) }));
29
+ return (_jsx(Li, { children: _jsxs(Button, { type: "button", variant: "ghost", onClick: () => onSelect(suggestion), onMouseEnter: () => onHover(itemIndex), className: `w-full flex items-center gap-3 px-4 py-3 text-left transition-colors border-b border-[var(--appkit-color-border)] last:border-b-0 ${isActive ? "bg-[var(--appkit-color-surface)] bg-[var(--appkit-color-surface-elevated)]" : CLS_HOVER_ROW}`, children: [_jsx(Span, { size: "sm", children: typeIcons[suggestion.type] }), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Text, { size: "sm", className: CLS_TRUNCATE, children: suggestion.title }), suggestion.subtitle && (_jsx(Text, { variant: "secondary", size: "xs", className: "truncate", children: suggestion.subtitle }))] }), _jsx(Span, { size: "xs", className: `${typeBadges[suggestion.type]}`, rounded: "full", padding: "pill-xs", children: suggestion.type })] }) }));
30
30
  }
31
31
  export function Search({ isOpen, onClose, onSearch, onOpen, value, onChange, placeholder, deferred = true, debounceMs = 300, onClear, className, router, quickLinks = [], labels, suggestionTypeIcons, suggestionTypeBadges, resourceTypes, defaultResourceType = "products", storageKey = "letitrip_search_type", }) {
32
32
  const isInlineMode = value !== undefined;
@@ -174,7 +174,7 @@ export function Search({ isOpen, onClose, onSearch, onOpen, value, onChange, pla
174
174
  return (_jsx(Li, { children: _jsxs(Button, { type: "button", variant: "ghost", onClick: () => {
175
175
  setIsInlineOpen(false);
176
176
  router.push(link.href);
177
- }, onMouseEnter: () => setActiveIndex(index), className: `w-full flex items-center gap-3 px-4 py-2.5 text-left transition-colors border-b border-zinc-200 dark:border-slate-700 ${isActive ? "bg-zinc-100 dark:bg-slate-800" : CLS_HOVER_ROW}`, children: [_jsx(Icon, { className: CLS_ICON_ROW }), _jsx(Text, { size: "sm", className: CLS_TRUNCATE, children: link.label })] }) }, `inline-link-${link.href}`));
177
+ }, onMouseEnter: () => setActiveIndex(index), className: `w-full flex items-center gap-3 px-4 py-2.5 text-left transition-colors border-b border-[var(--appkit-color-border)] ${isActive ? "bg-[var(--appkit-color-surface)] bg-[var(--appkit-color-surface-elevated)]" : CLS_HOVER_ROW}`, children: [_jsx(Icon, { className: CLS_ICON_ROW }), _jsx(Text, { size: "sm", className: CLS_TRUNCATE, children: link.label })] }) }, `inline-link-${link.href}`));
178
178
  };
179
179
  const handleInlineKeyDown = (event) => {
180
180
  if (event.key === "ArrowDown") {
@@ -216,15 +216,15 @@ export function Search({ isOpen, onClose, onSearch, onOpen, value, onChange, pla
216
216
  if (inlineBlurRef.current)
217
217
  clearTimeout(inlineBlurRef.current);
218
218
  inlineBlurRef.current = setTimeout(() => setIsInlineOpen(false), 120);
219
- }, placeholder: placeholder ?? labels.placeholder, className: "w-full rounded-lg border border-zinc-300 bg-white pl-9 text-zinc-900 placeholder:text-zinc-400 focus:border-primary focus:ring-2 focus:ring-primary/20 dark:border-slate-700 dark:bg-slate-900 dark:text-white dark:placeholder:text-slate-500" }), query && (_jsx(Button, { rounded: "full", textColor: "faint", type: "button", variant: "ghost", onClick: handleClear, className: "absolute right-3 p-[0.125rem] hover:text-[var(--appkit-color-text-muted)] dark:hover:text-[var(--appkit-color-text)] transition-colors", "aria-label": labels.clearAriaLabel, children: _jsx("svg", { className: "w-4 h-4", "aria-hidden": "true", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) }))] }), resourceTypes && resourceTypes.length > 0 && (_jsx("select", { value: selectedType, onChange: (e) => handleTypeChange(e.target.value), "aria-label": labels.resourceTypeLabel ?? "Search in", className: "flex-shrink-0 rounded-lg border border-zinc-300 bg-white px-2 py-2 text-sm text-zinc-700 focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20 dark:border-slate-700 dark:bg-slate-900 dark:text-zinc-300 cursor-pointer", children: resourceTypes.map((opt) => (_jsx("option", { value: opt.value, children: opt.label }, opt.value))) })), deferred && (_jsx(Button, { rounded: "lg", paddingX: "sm", paddingY: "sm", type: "button", variant: "primary", onClick: handleDeferredSubmit, "aria-label": labels.ariaLabel, className: "flex-shrink-0", children: _jsx("svg", { className: "w-4 h-4", "aria-hidden": "true", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: SVG_PATH_SEARCH }) }) })), isInlineOpen && (filteredQuickLinks.length > 0 || query) && (_jsxs("div", { className: "absolute top-full left-0 right-0 mt-2 rounded-xl overflow-hidden border border-zinc-200 bg-white shadow-lg dark:border-slate-700 dark:bg-slate-900 [z-index:var(--appkit-z-dropdown)]", onMouseDown: (event) => event.preventDefault(), children: [filteredQuickLinks.length > 0 && (_jsx(Ul, { children: filteredQuickLinks.map((link, index) => renderInlineQuickLink(link, index)) })), query && suggestionsLoading && (_jsx(Div, { padding: "inline", children: _jsx(Text, { variant: "secondary", size: "sm", children: labels.searching }) })), query &&
219
+ }, placeholder: placeholder ?? labels.placeholder, className: "w-full rounded-lg border border-zinc-300 bg-[var(--appkit-color-surface)] pl-9 text-zinc-900 placeholder:text-zinc-400 focus:border-primary focus:ring-2 focus:ring-primary/20 border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] dark:text-white dark:placeholder:text-slate-500" }), query && (_jsx(Button, { rounded: "full", textColor: "faint", type: "button", variant: "ghost", onClick: handleClear, className: "absolute right-3 p-[0.125rem] hover:text-[var(--appkit-color-text-muted)] dark:hover:text-[var(--appkit-color-text)] transition-colors", "aria-label": labels.clearAriaLabel, children: _jsx("svg", { className: "w-4 h-4", "aria-hidden": "true", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) }))] }), resourceTypes && resourceTypes.length > 0 && (_jsx("select", { value: selectedType, onChange: (e) => handleTypeChange(e.target.value), "aria-label": labels.resourceTypeLabel ?? "Search in", className: "flex-shrink-0 rounded-lg border border-zinc-300 bg-white px-2 py-2 text-sm text-zinc-700 focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20 border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] text-[var(--appkit-color-text-muted)] cursor-pointer", children: resourceTypes.map((opt) => (_jsx("option", { value: opt.value, children: opt.label }, opt.value))) })), deferred && (_jsx(Button, { rounded: "lg", paddingX: "sm", paddingY: "sm", type: "button", variant: "primary", onClick: handleDeferredSubmit, "aria-label": labels.ariaLabel, className: "flex-shrink-0", children: _jsx("svg", { className: "w-4 h-4", "aria-hidden": "true", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: SVG_PATH_SEARCH }) }) })), isInlineOpen && (filteredQuickLinks.length > 0 || query) && (_jsxs("div", { className: "absolute top-full left-0 right-0 mt-2 rounded-xl overflow-hidden border border-zinc-200 bg-[var(--appkit-color-surface)] shadow-lg border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] [z-index:var(--appkit-z-dropdown)]", onMouseDown: (event) => event.preventDefault(), children: [filteredQuickLinks.length > 0 && (_jsx(Ul, { children: filteredQuickLinks.map((link, index) => renderInlineQuickLink(link, index)) })), query && suggestionsLoading && (_jsx(Div, { padding: "inline", children: _jsx(Text, { variant: "secondary", size: "sm", children: labels.searching }) })), query &&
220
220
  suggestions.slice(0, 5).map((suggestion, suggestionIndex) => {
221
221
  const itemIndex = inlineQuickLinkItems.length + suggestionIndex;
222
222
  const isActive = activeIndex === itemIndex;
223
- return (_jsxs(Button, { type: "button", variant: "ghost", onClick: () => handleSuggestionClick(suggestion), onMouseEnter: () => setActiveIndex(itemIndex), className: `w-full flex items-center gap-3 px-4 py-2.5 text-left transition-colors border-b border-zinc-200 dark:border-slate-700 ${isActive ? "bg-zinc-100 dark:bg-slate-800" : CLS_HOVER_ROW}`, children: [_jsx(Span, { size: "sm", children: typeIcons[suggestion.type] }), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Text, { size: "sm", className: CLS_TRUNCATE, children: suggestion.title }), suggestion.subtitle && (_jsx(Text, { variant: "secondary", size: "xs", className: "truncate", children: suggestion.subtitle }))] })] }, `inline-suggestion-${suggestion.objectID}`));
223
+ return (_jsxs(Button, { type: "button", variant: "ghost", onClick: () => handleSuggestionClick(suggestion), onMouseEnter: () => setActiveIndex(itemIndex), className: `w-full flex items-center gap-3 px-4 py-2.5 text-left transition-colors border-b border-[var(--appkit-color-border)] ${isActive ? "bg-[var(--appkit-color-surface)] bg-[var(--appkit-color-surface-elevated)]" : CLS_HOVER_ROW}`, children: [_jsx(Span, { size: "sm", children: typeIcons[suggestion.type] }), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Text, { size: "sm", className: CLS_TRUNCATE, children: suggestion.title }), suggestion.subtitle && (_jsx(Text, { variant: "secondary", size: "xs", className: "truncate", children: suggestion.subtitle }))] })] }, `inline-suggestion-${suggestion.objectID}`));
224
224
  }), query.trim() && (_jsxs(Button, { type: "button", variant: "ghost", onClick: () => {
225
225
  handleDeferredSubmit();
226
226
  setIsInlineOpen(false);
227
- }, onMouseEnter: () => setActiveIndex(inlineItems.length - 1), className: `w-full flex items-center gap-2 px-4 py-3 text-left transition-colors ${activeIndex === inlineItems.length - 1 ? "bg-zinc-100 dark:bg-slate-800" : CLS_HOVER_ROW}`, children: [_jsx("svg", { className: CLS_ICON_ROW, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: SVG_PATH_SEARCH }) }), _jsx(Text, { size: "sm", className: CLS_TRUNCATE, children: labels.browseProducts(query) })] }))] }))] }));
227
+ }, onMouseEnter: () => setActiveIndex(inlineItems.length - 1), className: `w-full flex items-center gap-2 px-4 py-3 text-left transition-colors ${activeIndex === inlineItems.length - 1 ? "bg-[var(--appkit-color-surface)] bg-[var(--appkit-color-surface-elevated)]" : CLS_HOVER_ROW}`, children: [_jsx("svg", { className: CLS_ICON_ROW, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: SVG_PATH_SEARCH }) }), _jsx(Text, { size: "sm", className: CLS_TRUNCATE, children: labels.browseProducts(query) })] }))] }))] }));
228
228
  }
229
229
  const overlayQuery = query.toLowerCase();
230
230
  const filteredSiteLinks = query
@@ -292,13 +292,13 @@ export function Search({ isOpen, onClose, onSearch, onOpen, value, onChange, pla
292
292
  };
293
293
  if (!isOpen)
294
294
  return null;
295
- return (_jsx(Div, { border: "bottom-subtle", className: "animate-[fadeIn_150ms_ease-out]", surface: "default", shadow: "md", children: _jsxs(Div, { className: "container mx-auto md:py-[1rem] relative", padding: "inline", children: [_jsxs(Row, { gap: "sm", className: "md:gap-[0.75rem]", children: [_jsx(Div, { className: "flex-1 relative", children: _jsx(Input, { ref: inputRef, bare: true, type: "search", placeholder: placeholder ?? labels.placeholder, value: query, onChange: (event) => setQuery(event.target.value), onKeyDown: handleOverlayKeyDown, className: "w-full rounded-lg border border-zinc-300 bg-white text-zinc-900 placeholder:text-zinc-400 focus:border-primary focus:ring-2 focus:ring-primary/20 dark:border-slate-700 dark:bg-slate-900 dark:text-white dark:placeholder:text-slate-500" }) }), resourceTypes && resourceTypes.length > 0 && (_jsx("select", { value: selectedType, onChange: (e) => handleTypeChange(e.target.value), "aria-label": labels.resourceTypeLabel ?? "Search in", className: "flex-shrink-0 rounded-lg border border-zinc-300 bg-white px-2 py-2 text-sm text-zinc-700 focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20 dark:border-slate-700 dark:bg-slate-900 dark:text-zinc-300 cursor-pointer", children: resourceTypes.map((opt) => (_jsx("option", { value: opt.value, children: opt.label }, opt.value))) })), _jsxs(Button, { gap: "md", onClick: handleOverlaySearch, variant: "primary", size: "md", className: "hidden sm:", children: [_jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: SVG_PATH_SEARCH }) }), labels.title] }), _jsx(Button, { rounded: "xl", variant: "ghost", onClick: () => onClose?.(), className: "p-2.5 md:p-3 transition-colors text-zinc-500 hover:bg-zinc-100 hover:text-zinc-700 dark:text-zinc-400 dark:hover:bg-slate-800 dark:hover:text-zinc-200 flex-shrink-0", "aria-label": labels.closeAriaLabel, children: _jsx("svg", { className: "w-6 h-6 md:w-7 md:h-7", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }), (filteredSiteLinks.length > 0 || query) && (_jsxs(Stack, { className: "absolute top-full left-0 right-0 z-50 pt-[0.5rem] pb-[1rem]", padding: "x-md", gap: "sm", children: [filteredSiteLinks.length > 0 && !suggestionsLoading && (_jsxs(Div, { className: `${__O.hidden}`, rounded: "xl", shadow: "lg", surface: "default", border: "default", children: [_jsx(Div, { border: "default", className: "border-b", paddingY: "y-xs", paddingX: "x-md", children: _jsx(Text, { variant: "secondary", size: "xs", className: "uppercase tracking-wider", weight: "semibold", children: labels.quickLinks }) }), _jsx(Ul, { children: filteredSiteLinks.map((link) => {
295
+ return (_jsx(Div, { border: "bottom-subtle", className: "animate-[fadeIn_150ms_ease-out]", surface: "default", shadow: "md", children: _jsxs(Div, { className: "container mx-auto md:py-[1rem] relative", padding: "inline", children: [_jsxs(Row, { gap: "sm", className: "md:gap-[0.75rem]", children: [_jsx(Div, { className: "flex-1 relative", children: _jsx(Input, { ref: inputRef, bare: true, type: "search", placeholder: placeholder ?? labels.placeholder, value: query, onChange: (event) => setQuery(event.target.value), onKeyDown: handleOverlayKeyDown, className: "w-full rounded-lg border border-zinc-300 bg-[var(--appkit-color-surface)] text-zinc-900 placeholder:text-zinc-400 focus:border-primary focus:ring-2 focus:ring-primary/20 border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] dark:text-white dark:placeholder:text-slate-500" }) }), resourceTypes && resourceTypes.length > 0 && (_jsx("select", { value: selectedType, onChange: (e) => handleTypeChange(e.target.value), "aria-label": labels.resourceTypeLabel ?? "Search in", className: "flex-shrink-0 rounded-lg border border-zinc-300 bg-white px-2 py-2 text-sm text-zinc-700 focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20 border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] text-[var(--appkit-color-text-muted)] cursor-pointer", children: resourceTypes.map((opt) => (_jsx("option", { value: opt.value, children: opt.label }, opt.value))) })), _jsxs(Button, { gap: "md", onClick: handleOverlaySearch, variant: "primary", size: "md", className: "hidden sm:", children: [_jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: SVG_PATH_SEARCH }) }), labels.title] }), _jsx(Button, { rounded: "xl", variant: "ghost", onClick: () => onClose?.(), className: "p-2.5 md:p-3 transition-colors text-[var(--appkit-color-text-muted)] hover:bg-[var(--appkit-color-surface)] hover:text-zinc-700 text-[var(--appkit-color-text-muted)] hover:bg-[var(--appkit-color-surface-elevated)] hover:text-[var(--appkit-color-text-muted)] flex-shrink-0", "aria-label": labels.closeAriaLabel, children: _jsx("svg", { className: "w-6 h-6 md:w-7 md:h-7", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }), (filteredSiteLinks.length > 0 || query) && (_jsxs(Stack, { className: "absolute top-full left-0 right-0 z-50 pt-[0.5rem] pb-[1rem]", padding: "x-md", gap: "sm", children: [filteredSiteLinks.length > 0 && !suggestionsLoading && (_jsxs(Div, { className: `${__O.hidden}`, rounded: "xl", shadow: "lg", surface: "default", border: "default", children: [_jsx(Div, { border: "default", className: "border-b", paddingY: "y-xs", paddingX: "x-md", children: _jsx(Text, { variant: "secondary", size: "xs", className: "uppercase tracking-wider", weight: "semibold", children: labels.quickLinks }) }), _jsx(Ul, { children: filteredSiteLinks.map((link) => {
296
296
  const Icon = link.icon;
297
297
  const itemIndex = quickLinkItems.findIndex((item) => item.link.href === link.href);
298
298
  const isActive = activeIndex === itemIndex;
299
299
  return (_jsx(Li, { children: _jsxs(Button, { type: "button", variant: "ghost", onClick: () => {
300
300
  onClose?.();
301
301
  router.push(link.href);
302
- }, onMouseEnter: () => setActiveIndex(itemIndex), className: `w-full flex items-center gap-3 px-4 py-2.5 text-left transition-colors border-b border-zinc-200 dark:border-slate-700 last:border-b-0 ${isActive ? "bg-zinc-100 dark:bg-slate-800" : CLS_HOVER_ROW}`, children: [_jsx(Icon, { className: CLS_ICON_ROW }), _jsx(Text, { size: "sm", weight: "medium", children: link.label })] }) }, link.href));
303
- }) })] })), query && (_jsxs(Div, { className: `${__O.hidden}`, rounded: "xl", shadow: "lg", surface: "default", border: "default", children: [suggestionsLoading ? (_jsx(Div, { padding: "inline", children: _jsx(Text, { variant: "secondary", size: "sm", children: labels.searching }) })) : suggestions.length > 0 ? (_jsx(Ul, { children: suggestions.map((suggestion, suggestionIndex) => (_jsx(SuggestionItem, { suggestion: suggestion, itemIndex: getOverlaySuggestionIndex(suggestionIndex), activeIndex: activeIndex, onSelect: handleSuggestionClick, onHover: setActiveIndex, typeIcons: typeIcons, typeBadges: typeBadges }, suggestion.objectID))) })) : null, _jsxs(Button, { type: "button", variant: "ghost", onClick: handleOverlaySearch, onMouseEnter: () => setActiveIndex(overlayItems.length - 1), className: `w-full flex items-center gap-2 px-4 py-3 text-left transition-colors ${activeIndex === overlayItems.length - 1 ? "bg-zinc-100 dark:bg-slate-800" : CLS_HOVER_ROW}${suggestions.length > 0 ? " border-t border-zinc-200 dark:border-slate-700" : ""}`, children: [_jsx("svg", { className: CLS_ICON_ROW, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: SVG_PATH_SEARCH }) }), _jsx(Text, { size: "sm", weight: "medium", children: labels.browseProducts(query) })] })] }))] }))] }) }));
302
+ }, onMouseEnter: () => setActiveIndex(itemIndex), className: `w-full flex items-center gap-3 px-4 py-2.5 text-left transition-colors border-b border-[var(--appkit-color-border)] last:border-b-0 ${isActive ? "bg-[var(--appkit-color-surface)] bg-[var(--appkit-color-surface-elevated)]" : CLS_HOVER_ROW}`, children: [_jsx(Icon, { className: CLS_ICON_ROW }), _jsx(Text, { size: "sm", weight: "medium", children: link.label })] }) }, link.href));
303
+ }) })] })), query && (_jsxs(Div, { className: `${__O.hidden}`, rounded: "xl", shadow: "lg", surface: "default", border: "default", children: [suggestionsLoading ? (_jsx(Div, { padding: "inline", children: _jsx(Text, { variant: "secondary", size: "sm", children: labels.searching }) })) : suggestions.length > 0 ? (_jsx(Ul, { children: suggestions.map((suggestion, suggestionIndex) => (_jsx(SuggestionItem, { suggestion: suggestion, itemIndex: getOverlaySuggestionIndex(suggestionIndex), activeIndex: activeIndex, onSelect: handleSuggestionClick, onHover: setActiveIndex, typeIcons: typeIcons, typeBadges: typeBadges }, suggestion.objectID))) })) : null, _jsxs(Button, { type: "button", variant: "ghost", onClick: handleOverlaySearch, onMouseEnter: () => setActiveIndex(overlayItems.length - 1), className: `w-full flex items-center gap-2 px-4 py-3 text-left transition-colors ${activeIndex === overlayItems.length - 1 ? "bg-[var(--appkit-color-surface)] bg-[var(--appkit-color-surface-elevated)]" : CLS_HOVER_ROW}${suggestions.length > 0 ? " border-t border-[var(--appkit-color-border)]" : ""}`, children: [_jsx("svg", { className: CLS_ICON_ROW, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: SVG_PATH_SEARCH }) }), _jsx(Text, { size: "sm", weight: "medium", children: labels.browseProducts(query) })] })] }))] }))] }) }));
304
304
  }
@@ -17,5 +17,5 @@ export function SearchFiltersRow({ urlCategory, categories, urlMinPrice, urlMaxP
17
17
  return (_jsxs(Row, { wrap: true, gap: "md", align: "end", children: [_jsxs(Stack, { gap: "xs", children: [_jsx(Label, { size: "sm", weight: "medium", color: "muted", children: L.categoryFilter }), _jsx(Select, { value: urlCategory, onValueChange: (value) => onCategoryChange(value), options: [
18
18
  { value: "", label: L.allCategories },
19
19
  ...categories.map((cat) => ({ value: cat.id, label: cat.name })),
20
- ], className: "rounded-lg border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-primary-500/20" })] }), _jsxs(Stack, { gap: "xs", children: [_jsx(Label, { size: "sm", weight: "medium", color: "muted", children: L.priceRange }), _jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Input, { type: "number", min: 0, value: minPrice, onChange: (e) => setMinPrice(e.target.value), placeholder: L.minPrice, className: "w-28 rounded-lg border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-primary-500/20" }), _jsx(Span, { size: "sm", color: "muted", children: "\u2013" }), _jsx(Input, { type: "number", min: 0, value: maxPrice, onChange: (e) => setMaxPrice(e.target.value), placeholder: L.maxPrice, className: "w-28 rounded-lg border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-primary-500/20" }), _jsx(Button, { rounded: "lg", type: "button", variant: "primary", size: "sm", onClick: () => onPriceFilter(minPrice, maxPrice), className: "h-10 px-4 bg-primary-600 hover:bg-primary-700 text-white text-sm font-medium transition-colors", children: L.apply })] })] }), showClear && (_jsx(Button, { rounded: "lg", type: "button", variant: "outline", size: "sm", onClick: onClearFilters, paddingX: "md", textSize: "sm", className: "h-10 border border-[var(--appkit-color-border)] text-[var(--appkit-color-text)] hover:bg-[var(--appkit-color-surface-elevated)] transition-colors", children: L.clearFilters }))] }));
20
+ ], className: "rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-input)] px-3 py-2 text-sm text-[var(--appkit-color-text)] focus:outline-none focus:ring-2 focus:ring-primary-500/20" })] }), _jsxs(Stack, { gap: "xs", children: [_jsx(Label, { size: "sm", weight: "medium", color: "muted", children: L.priceRange }), _jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Input, { type: "number", min: 0, value: minPrice, onChange: (e) => setMinPrice(e.target.value), placeholder: L.minPrice, className: "w-28 rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-input)] px-3 py-2 text-sm text-[var(--appkit-color-text)] focus:outline-none focus:ring-2 focus:ring-primary-500/20" }), _jsx(Span, { size: "sm", color: "muted", children: "\u2013" }), _jsx(Input, { type: "number", min: 0, value: maxPrice, onChange: (e) => setMaxPrice(e.target.value), placeholder: L.maxPrice, className: "w-28 rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-input)] px-3 py-2 text-sm text-[var(--appkit-color-text)] focus:outline-none focus:ring-2 focus:ring-primary-500/20" }), _jsx(Button, { rounded: "lg", type: "button", variant: "primary", size: "sm", onClick: () => onPriceFilter(minPrice, maxPrice), className: "h-10 px-4 bg-primary-600 hover:bg-primary-700 text-white text-sm font-medium transition-colors", children: L.apply })] })] }), showClear && (_jsx(Button, { rounded: "lg", type: "button", variant: "outline", size: "sm", onClick: onClearFilters, paddingX: "md", textSize: "sm", className: "h-10 border border-[var(--appkit-color-border)] text-[var(--appkit-color-text)] hover:bg-[var(--appkit-color-surface-elevated)] transition-colors", children: L.clearFilters }))] }));
21
21
  }
@@ -26,10 +26,10 @@ export function SearchResultsSection({ products, total, totalPages, urlQ, urlSor
26
26
  showing: products.length,
27
27
  urlSort,
28
28
  onSortChange,
29
- })) : (_jsxs(Row, { justify: "between", children: [_jsx(Text, { size: "sm", color: "muted", children: L.showing(products.length, total) }), sortOptions.length > 0 && (_jsx(Select, { value: urlSort, onValueChange: onSortChange, options: sortOptions, className: "rounded-lg border border-zinc-200 dark:border-slate-700 bg-white dark:bg-slate-800/60 px-3 py-1.5 text-sm text-zinc-900 dark:text-zinc-100 focus:outline-none" }))] })), renderProducts ? (renderProducts(products)) : (_jsx(Grid, { cols: "statTiles", children: products.map((p) => (_jsx(Div, { children: renderItem(p) }, p.id))) })), totalPages > 1 &&
29
+ })) : (_jsxs(Row, { justify: "between", children: [_jsx(Text, { size: "sm", color: "muted", children: L.showing(products.length, total) }), sortOptions.length > 0 && (_jsx(Select, { value: urlSort, onValueChange: onSortChange, options: sortOptions, className: "rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-input)] px-3 py-1.5 text-sm text-[var(--appkit-color-text)] focus:outline-none" }))] })), renderProducts ? (renderProducts(products)) : (_jsx(Grid, { cols: "statTiles", children: products.map((p) => (_jsx(Div, { children: renderItem(p) }, p.id))) })), totalPages > 1 &&
30
30
  (renderPagination ? (renderPagination({
31
31
  urlPage,
32
32
  totalPages,
33
33
  onPageChange,
34
- })) : (_jsxs(Row, { align: "center", justify: "center", gap: "sm", padding: "t-md", children: [_jsx(Button, { rounded: "lg", type: "button", variant: "outline", size: "sm", onClick: () => onPageChange(urlPage - 1), disabled: urlPage <= 1, className: "px-4 py-2 border border-zinc-200 dark:border-slate-700 text-sm text-zinc-700 dark:text-zinc-300 disabled:opacity-40 hover:bg-zinc-100 dark:hover:bg-slate-800 transition-colors", children: L.prevPage }), _jsxs(Span, { size: "sm", className: "tabular-nums", color: "muted", children: [urlPage, " / ", totalPages] }), _jsx(Button, { rounded: "lg", type: "button", variant: "outline", size: "sm", onClick: () => onPageChange(urlPage + 1), disabled: urlPage >= totalPages, className: "px-4 py-2 border border-zinc-200 dark:border-slate-700 text-sm text-zinc-700 dark:text-zinc-300 disabled:opacity-40 hover:bg-zinc-100 dark:hover:bg-slate-800 transition-colors", children: L.nextPage })] })))] }));
34
+ })) : (_jsxs(Row, { align: "center", justify: "center", gap: "sm", padding: "t-md", children: [_jsx(Button, { rounded: "lg", type: "button", variant: "outline", size: "sm", onClick: () => onPageChange(urlPage - 1), disabled: urlPage <= 1, className: "px-4 py-2 border border-[var(--appkit-color-border)] text-sm text-[var(--appkit-color-text-muted)] disabled:opacity-40 hover:bg-[var(--appkit-color-surface)] hover:bg-[var(--appkit-color-surface-elevated)] transition-colors", children: L.prevPage }), _jsxs(Span, { size: "sm", className: "tabular-nums", color: "muted", children: [urlPage, " / ", totalPages] }), _jsx(Button, { rounded: "lg", type: "button", variant: "outline", size: "sm", onClick: () => onPageChange(urlPage + 1), disabled: urlPage >= totalPages, className: "px-4 py-2 border border-[var(--appkit-color-border)] text-sm text-[var(--appkit-color-text-muted)] disabled:opacity-40 hover:bg-[var(--appkit-color-surface)] hover:bg-[var(--appkit-color-surface-elevated)] transition-colors", children: L.nextPage })] })))] }));
35
35
  }