@mohasinac/appkit 2.7.26 → 2.7.30

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 (363) hide show
  1. package/dist/_internal/client/features/classified/ClassifiedDetailView.js +2 -2
  2. package/dist/_internal/client/features/digital-code/CodeRevealPanel.js +2 -2
  3. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +1 -1
  4. package/dist/_internal/server/features/checkout/actions.js +42 -35
  5. package/dist/_internal/server/features/classified/adapters.d.ts +21 -0
  6. package/dist/_internal/server/features/classified/adapters.js +24 -0
  7. package/dist/_internal/server/features/classified/index.d.ts +3 -0
  8. package/dist/_internal/server/features/classified/index.js +3 -0
  9. package/dist/_internal/server/features/classified/metadata.d.ts +8 -0
  10. package/dist/_internal/server/features/classified/metadata.js +43 -0
  11. package/dist/_internal/server/features/classified/og.d.ts +30 -0
  12. package/dist/_internal/server/features/classified/og.js +76 -0
  13. package/dist/_internal/server/features/digital-code/adapters.d.ts +21 -0
  14. package/dist/_internal/server/features/digital-code/adapters.js +29 -0
  15. package/dist/_internal/server/features/digital-code/index.d.ts +3 -0
  16. package/dist/_internal/server/features/digital-code/index.js +3 -0
  17. package/dist/_internal/server/features/digital-code/metadata.d.ts +8 -0
  18. package/dist/_internal/server/features/digital-code/metadata.js +36 -0
  19. package/dist/_internal/server/features/digital-code/og.d.ts +27 -0
  20. package/dist/_internal/server/features/digital-code/og.js +77 -0
  21. package/dist/_internal/server/features/live/adapters.d.ts +21 -0
  22. package/dist/_internal/server/features/live/adapters.js +34 -0
  23. package/dist/_internal/server/features/live/index.d.ts +3 -0
  24. package/dist/_internal/server/features/live/index.js +3 -0
  25. package/dist/_internal/server/features/live/metadata.d.ts +8 -0
  26. package/dist/_internal/server/features/live/metadata.js +39 -0
  27. package/dist/_internal/server/features/live/og.d.ts +27 -0
  28. package/dist/_internal/server/features/live/og.js +72 -0
  29. package/dist/_internal/server/features/promotions/actions.js +4 -3
  30. package/dist/_internal/server/jobs/core/onOrderCreate.js +19 -16
  31. package/dist/_internal/server/jobs/core/onOrderStatusChange.js +25 -22
  32. package/dist/_internal/server/jobs/core/onProductWrite.js +48 -58
  33. package/dist/_internal/shared/actions/action-registry.js +310 -8
  34. package/dist/_internal/shared/features/blog/schema.d.ts +4 -4
  35. package/dist/_internal/shared/features/brands/schema.d.ts +5 -5
  36. package/dist/_internal/shared/features/cart/schema.d.ts +18 -18
  37. package/dist/_internal/shared/features/categories/bundle-copy.d.ts +1 -1
  38. package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +38 -38
  39. package/dist/_internal/shared/features/events/schema.d.ts +8 -8
  40. package/dist/_internal/shared/features/orders/schema.d.ts +8 -8
  41. package/dist/_internal/shared/features/products/schema.d.ts +42 -42
  42. package/dist/_internal/shared/features/promotions/schema.d.ts +4 -4
  43. package/dist/_internal/shared/features/reviews/schema.d.ts +1 -1
  44. package/dist/_internal/shared/media/limits.js +4 -3
  45. package/dist/client.d.ts +2 -0
  46. package/dist/client.js +1 -0
  47. package/dist/configs/next.js +4 -0
  48. package/dist/constants/table-keys.d.ts +6 -0
  49. package/dist/constants/table-keys.js +9 -0
  50. package/dist/core/hooks/useSyncManager.js +9 -8
  51. package/dist/features/about/components/FeesView.js +10 -7
  52. package/dist/features/about/components/HelpPageView.js +10 -1
  53. package/dist/features/about/components/HowAuctionsWorkView.js +10 -1
  54. package/dist/features/about/components/HowCheckoutWorksView.js +10 -1
  55. package/dist/features/about/components/HowOffersWorkView.js +10 -1
  56. package/dist/features/about/components/HowOrdersWorkView.js +10 -1
  57. package/dist/features/about/components/HowPayoutsWorkView.js +10 -1
  58. package/dist/features/about/components/HowPreOrdersWorkView.js +10 -1
  59. package/dist/features/about/components/HowReviewsWorkView.js +10 -1
  60. package/dist/features/about/components/PublicProfileView.js +44 -14
  61. package/dist/features/about/components/SecurityPrivacyView.js +7 -1
  62. package/dist/features/account/components/AddressesIndexListing.js +2 -2
  63. package/dist/features/account/components/NotificationBell.js +27 -16
  64. package/dist/features/account/components/NotificationPreferencesPanel.d.ts +9 -0
  65. package/dist/features/account/components/NotificationPreferencesPanel.js +91 -0
  66. package/dist/features/account/components/UserSidebar.js +4 -4
  67. package/dist/features/account/components/UserSupportView.js +16 -6
  68. package/dist/features/account/components/index.d.ts +2 -0
  69. package/dist/features/account/components/index.js +1 -0
  70. package/dist/features/account/schemas/index.d.ts +4 -4
  71. package/dist/features/account/types/index.d.ts +34 -0
  72. package/dist/features/admin/actions/admin-actions.js +4 -3
  73. package/dist/features/admin/actions/notification-actions.d.ts +24 -22
  74. package/dist/features/admin/actions/notification-actions.js +122 -22
  75. package/dist/features/admin/components/AdminAdEditorView.js +29 -15
  76. package/dist/features/admin/components/AdminAdsView.js +22 -28
  77. package/dist/features/admin/components/AdminAllEventEntriesView.js +6 -1
  78. package/dist/features/admin/components/AdminBidsView.js +10 -3
  79. package/dist/features/admin/components/AdminBlogEditorView.js +2 -2
  80. package/dist/features/admin/components/AdminBlogView.js +8 -3
  81. package/dist/features/admin/components/AdminBrandsView.js +7 -2
  82. package/dist/features/admin/components/AdminBundleEditorView.js +5 -2
  83. package/dist/features/admin/components/AdminCarouselEditorView.js +6 -3
  84. package/dist/features/admin/components/AdminCarouselView.js +13 -7
  85. package/dist/features/admin/components/AdminCategoriesView.js +8 -3
  86. package/dist/features/admin/components/AdminCategoryEditorView.js +2 -2
  87. package/dist/features/admin/components/AdminContactView.js +6 -1
  88. package/dist/features/admin/components/AdminCouponEditorView.js +8 -2
  89. package/dist/features/admin/components/AdminCouponsView.js +6 -1
  90. package/dist/features/admin/components/AdminEmployeeEditorView.js +12 -9
  91. package/dist/features/admin/components/AdminFaqEditorView.js +2 -2
  92. package/dist/features/admin/components/AdminFaqsView.js +7 -2
  93. package/dist/features/admin/components/AdminFeaturesView.js +4 -3
  94. package/dist/features/admin/components/AdminMediaView.js +9 -8
  95. package/dist/features/admin/components/AdminNavigationView.js +10 -17
  96. package/dist/features/admin/components/AdminNewsletterView.js +6 -1
  97. package/dist/features/admin/components/AdminNotificationsView.js +11 -3
  98. package/dist/features/admin/components/AdminOrdersView.js +6 -1
  99. package/dist/features/admin/components/AdminPayoutsView.js +10 -3
  100. package/dist/features/admin/components/AdminPrizeDrawsView.js +10 -3
  101. package/dist/features/admin/components/AdminProductsView.js +18 -12
  102. package/dist/features/admin/components/AdminReviewsView.js +33 -24
  103. package/dist/features/admin/components/AdminScammerEditorView.js +3 -2
  104. package/dist/features/admin/components/AdminScammersView.js +28 -26
  105. package/dist/features/admin/components/AdminSectionsView.js +112 -99
  106. package/dist/features/admin/components/AdminSessionsView.js +10 -3
  107. package/dist/features/admin/components/AdminSidebar.js +4 -4
  108. package/dist/features/admin/components/AdminSiteSettingsView.js +45 -4
  109. package/dist/features/admin/components/AdminStoresView.js +6 -1
  110. package/dist/features/admin/components/AdminSublistingCategoriesView.js +0 -1
  111. package/dist/features/admin/components/AdminSupportTicketDetailView.js +1 -1
  112. package/dist/features/admin/components/AdminSupportTicketsView.js +32 -34
  113. package/dist/features/admin/components/AdminTeamView.js +6 -1
  114. package/dist/features/admin/components/AdminUserEditorView.js +8 -15
  115. package/dist/features/admin/components/AdminUsersView.js +6 -1
  116. package/dist/features/admin/components/AdminViewCards.js +4 -3
  117. package/dist/features/admin/components/DashboardStats.js +2 -2
  118. package/dist/features/admin/components/DataTable.js +2 -2
  119. package/dist/features/admin/components/sections/adminSectionsTypes.js +4 -3
  120. package/dist/features/admin/repository/chat.repository.js +8 -8
  121. package/dist/features/admin/repository/site-settings.repository.d.ts +1 -0
  122. package/dist/features/admin/repository/site-settings.repository.js +11 -9
  123. package/dist/features/admin/schemas/firestore.d.ts +38 -0
  124. package/dist/features/admin/schemas/firestore.js +15 -0
  125. package/dist/features/auctions/components/AuctionDetailPageView.js +13 -19
  126. package/dist/features/auctions/components/MarketplaceAuctionCard.js +18 -9
  127. package/dist/features/auctions/components/MarketplaceAuctionGrid.js +3 -2
  128. package/dist/features/auctions/components/index.d.ts +0 -1
  129. package/dist/features/auctions/components/index.js +0 -1
  130. package/dist/features/auctions/schemas/index.d.ts +14 -14
  131. package/dist/features/auth/actions/realtime-token-actions.js +19 -4
  132. package/dist/features/auth/components/RegisterForm.js +8 -4
  133. package/dist/features/auth/consent-otp.d.ts +2 -0
  134. package/dist/features/auth/consent-otp.js +8 -0
  135. package/dist/features/auth/schemas/firestore.d.ts +2 -0
  136. package/dist/features/auth/schemas/firestore.js +18 -25
  137. package/dist/features/auth/schemas/index.d.ts +2 -2
  138. package/dist/features/before-after/api/[id]/route.js +8 -6
  139. package/dist/features/before-after/schemas/index.d.ts +2 -2
  140. package/dist/features/blog/actions/blog-actions.d.ts +3 -3
  141. package/dist/features/blog/components/BlogIndexListing.js +21 -2
  142. package/dist/features/blog/components/BlogPostForm.js +11 -5
  143. package/dist/features/blog/components/BlogPostView.js +10 -2
  144. package/dist/features/blog/schemas/index.d.ts +18 -18
  145. package/dist/features/cart/components/CartDrawer.js +3 -2
  146. package/dist/features/cart/repository/cart.repository.js +4 -3
  147. package/dist/features/cart/utils/pending-ops.d.ts +1 -1
  148. package/dist/features/categories/api/[id]/route.js +4 -3
  149. package/dist/features/categories/api/route.js +4 -3
  150. package/dist/features/categories/components/BrandDetailPageView.js +2 -2
  151. package/dist/features/categories/components/BrandDetailTabs.js +2 -2
  152. package/dist/features/categories/components/BundleCollage.d.ts +8 -0
  153. package/dist/features/categories/components/BundleCollage.js +50 -0
  154. package/dist/features/categories/components/BundleDetailView.js +2 -10
  155. package/dist/features/categories/components/BundleItemsPicker.js +20 -13
  156. package/dist/features/categories/components/CategoriesIndexListing.js +28 -9
  157. package/dist/features/categories/components/CategoryDetailPageView.js +2 -2
  158. package/dist/features/categories/components/CategoryDetailTabs.js +2 -2
  159. package/dist/features/categories/components/CategoryProductsListing.js +52 -13
  160. package/dist/features/categories/components/index.d.ts +2 -0
  161. package/dist/features/categories/components/index.js +1 -0
  162. package/dist/features/categories/schemas/index.d.ts +6 -6
  163. package/dist/features/checkout/actions/checkout-actions.js +4 -3
  164. package/dist/features/checkout/hooks/usePaymentCheckout.js +31 -22
  165. package/dist/features/classified/components/ClassifiedFilters.d.ts +8 -0
  166. package/dist/features/classified/components/ClassifiedFilters.js +19 -0
  167. package/dist/features/classified/components/ClassifiedIndexListing.d.ts +4 -0
  168. package/dist/features/classified/components/ClassifiedIndexListing.js +110 -0
  169. package/dist/features/classified/components/ClassifiedListView.d.ts +6 -0
  170. package/dist/features/classified/components/ClassifiedListView.js +43 -0
  171. package/dist/features/classified/components/index.d.ts +6 -0
  172. package/dist/features/classified/components/index.js +3 -0
  173. package/dist/features/collections/api/[slug]/route.js +16 -12
  174. package/dist/features/collections/schemas/index.d.ts +5 -5
  175. package/dist/features/consultation/api/[id]/route.js +12 -9
  176. package/dist/features/consultation/components/ConsultationForm.js +3 -2
  177. package/dist/features/consultation/schemas/index.d.ts +6 -6
  178. package/dist/features/contact/email.js +77 -116
  179. package/dist/features/copilot/components/AdminCopilotView.js +12 -2
  180. package/dist/features/corporate/api/[id]/route.js +12 -9
  181. package/dist/features/corporate/components/CorporateInquiryForm.js +2 -1
  182. package/dist/features/digital-codes/components/DigitalCodeFilters.d.ts +8 -0
  183. package/dist/features/digital-codes/components/DigitalCodeFilters.js +16 -0
  184. package/dist/features/digital-codes/components/DigitalCodesIndexListing.d.ts +4 -0
  185. package/dist/features/digital-codes/components/DigitalCodesIndexListing.js +107 -0
  186. package/dist/features/digital-codes/components/DigitalCodesListView.d.ts +6 -0
  187. package/dist/features/digital-codes/components/DigitalCodesListView.js +37 -0
  188. package/dist/features/digital-codes/components/index.d.ts +6 -0
  189. package/dist/features/digital-codes/components/index.js +3 -0
  190. package/dist/features/events/actions/event-actions.js +4 -3
  191. package/dist/features/events/components/AdminEventEditorView.js +3 -2
  192. package/dist/features/events/components/AdminEventsView.js +4 -2
  193. package/dist/features/events/components/EventPollWidget.js +5 -5
  194. package/dist/features/events/components/EventsIndexListing.js +2 -2
  195. package/dist/features/events/schemas/index.d.ts +20 -20
  196. package/dist/features/faq/actions/faq-actions.d.ts +8 -8
  197. package/dist/features/faq/components/ContactCTA.js +3 -1
  198. package/dist/features/faq/components/FAQAccordion.js +1 -1
  199. package/dist/features/faq/schemas/index.d.ts +4 -4
  200. package/dist/features/filters/AsyncFacetSection.d.ts +18 -0
  201. package/dist/features/filters/AsyncFacetSection.js +65 -0
  202. package/dist/features/forms/Checkbox.js +2 -2
  203. package/dist/features/forms/Input.js +2 -2
  204. package/dist/features/forms/Radio.js +5 -5
  205. package/dist/features/forms/Select.js +2 -2
  206. package/dist/features/forms/Slider.js +2 -2
  207. package/dist/features/forms/Textarea.js +2 -2
  208. package/dist/features/homepage/api/[id]/route.js +4 -3
  209. package/dist/features/homepage/api/sections/[id]/route.js +12 -9
  210. package/dist/features/homepage/components/AdSlot.js +2 -1
  211. package/dist/features/homepage/components/AdvertisementBanner.js +5 -3
  212. package/dist/features/homepage/components/BrandsSection.js +2 -2
  213. package/dist/features/homepage/components/CTABannerSection.js +2 -2
  214. package/dist/features/homepage/components/CharacterHotspot.d.ts +2 -2
  215. package/dist/features/homepage/components/CharacterHotspot.js +119 -157
  216. package/dist/features/homepage/components/CharacterHotspotForm.js +25 -20
  217. package/dist/features/homepage/components/CustomCardsSection.js +8 -6
  218. package/dist/features/homepage/components/FeaturedProductsSection.js +2 -2
  219. package/dist/features/homepage/components/GoogleReviewsSection.js +3 -3
  220. package/dist/features/homepage/components/HeroBanner.js +5 -4
  221. package/dist/features/homepage/components/HeroCarousel.js +13 -26
  222. package/dist/features/homepage/components/HowItWorksSection.js +4 -2
  223. package/dist/features/homepage/components/SocialFeedSection.js +2 -2
  224. package/dist/features/homepage/components/SocialPostCard.js +3 -2
  225. package/dist/features/homepage/lib/social-feed-fetcher.js +6 -3
  226. package/dist/features/layout/AppLayoutShell.d.ts +8 -2
  227. package/dist/features/layout/AppLayoutShell.js +55 -84
  228. package/dist/features/layout/BottomActions.js +43 -48
  229. package/dist/features/layout/NavbarWithSettings.d.ts +6 -0
  230. package/dist/features/layout/NavbarWithSettings.js +11 -0
  231. package/dist/features/live/components/LiveItemFilters.d.ts +8 -0
  232. package/dist/features/live/components/LiveItemFilters.js +23 -0
  233. package/dist/features/live/components/LiveItemsIndexListing.d.ts +4 -0
  234. package/dist/features/live/components/LiveItemsIndexListing.js +108 -0
  235. package/dist/features/live/components/LiveItemsListView.d.ts +6 -0
  236. package/dist/features/live/components/LiveItemsListView.js +43 -0
  237. package/dist/features/live/components/index.d.ts +6 -0
  238. package/dist/features/live/components/index.js +3 -0
  239. package/dist/features/media/MediaLightbox.js +8 -14
  240. package/dist/features/media/types/index.d.ts +2 -2
  241. package/dist/features/media/upload/CameraCapture.js +2 -2
  242. package/dist/features/media/upload/ImageUpload.js +4 -2
  243. package/dist/features/media/upload/MediaUploadField.js +24 -8
  244. package/dist/features/media/upload/MediaUploadList.js +1 -1
  245. package/dist/features/orders/actions/order-actions.js +4 -3
  246. package/dist/features/orders/components/MarketplaceOrderCard.js +2 -1
  247. package/dist/features/orders/components/OrderFilters.js +12 -9
  248. package/dist/features/orders/schemas/index.d.ts +6 -6
  249. package/dist/features/pre-orders/api/[id]/route.js +12 -9
  250. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +5 -4
  251. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +27 -20
  252. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +17 -52
  253. package/dist/features/pre-orders/components/PreorderCard.d.ts +0 -9
  254. package/dist/features/pre-orders/components/PreorderCard.js +2 -13
  255. package/dist/features/pre-orders/components/index.d.ts +1 -1
  256. package/dist/features/pre-orders/components/index.js +1 -1
  257. package/dist/features/pre-orders/schemas/index.d.ts +10 -10
  258. package/dist/features/products/api/[id]/route.js +9 -7
  259. package/dist/features/products/api/route.js +1 -1
  260. package/dist/features/products/columns/productTableColumns.js +2 -2
  261. package/dist/features/products/components/AuctionsIndexListing.js +15 -51
  262. package/dist/features/products/components/BidHistory.js +2 -2
  263. package/dist/features/products/components/CompareOverlay.js +3 -2
  264. package/dist/features/products/components/MakeOfferButton.js +20 -14
  265. package/dist/features/products/components/MarketplacePrizeDrawCard.js +2 -1
  266. package/dist/features/products/components/PrizeDrawCollage.d.ts +1 -15
  267. package/dist/features/products/components/PrizeDrawCollage.js +54 -14
  268. package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -1
  269. package/dist/features/products/components/PrizeDrawEntryActions.js +2 -1
  270. package/dist/features/products/components/PrizeDrawItemsEditor.js +9 -7
  271. package/dist/features/products/components/PrizeDrawsIndexListing.js +18 -51
  272. package/dist/features/products/components/PrizeRevealModal.js +24 -14
  273. package/dist/features/products/components/ProductDetailPageView.js +2 -1
  274. package/dist/features/products/components/ProductFilters.js +8 -6
  275. package/dist/features/products/components/ProductForm.js +12 -10
  276. package/dist/features/products/components/ProductGalleryClient.js +2 -1
  277. package/dist/features/products/components/ProductGrid.js +11 -14
  278. package/dist/features/products/components/ProductsIndexListing.js +16 -52
  279. package/dist/features/products/components/ProductsIndexPageView.js +2 -2
  280. package/dist/features/products/schemas/index.d.ts +56 -56
  281. package/dist/features/products/schemas/product-features.validators.d.ts +14 -14
  282. package/dist/features/promotions/components/CouponsIndexListing.js +1 -1
  283. package/dist/features/promotions/schemas/index.d.ts +6 -6
  284. package/dist/features/reviews/actions/review-actions.js +6 -5
  285. package/dist/features/reviews/api/[id]/route.js +4 -3
  286. package/dist/features/reviews/components/ReviewDetailPageView.js +2 -2
  287. package/dist/features/reviews/components/ReviewDetailShell.js +6 -3
  288. package/dist/features/reviews/components/ReviewsIndexListing.js +2 -2
  289. package/dist/features/reviews/schemas/index.d.ts +6 -6
  290. package/dist/features/scams/components/ScamProfileView.js +19 -10
  291. package/dist/features/scams/components/ScamRegistryView.js +2 -1
  292. package/dist/features/search/components/Search.d.ts +1 -1
  293. package/dist/features/search/components/Search.js +56 -49
  294. package/dist/features/search/schemas/index.d.ts +5 -5
  295. package/dist/features/seller/actions/offer-actions.js +11 -9
  296. package/dist/features/seller/components/SellerAddressesView.js +6 -4
  297. package/dist/features/seller/components/SellerBidsView.js +2 -2
  298. package/dist/features/seller/components/SellerCouponsView.js +1 -1
  299. package/dist/features/seller/components/SellerOffersPanel.js +6 -1
  300. package/dist/features/seller/components/SellerOrdersView.js +1 -1
  301. package/dist/features/seller/components/SellerPayoutSettingsView.js +3 -3
  302. package/dist/features/seller/components/SellerPreOrdersView.js +5 -4
  303. package/dist/features/seller/components/SellerPrizeDrawsView.js +5 -4
  304. package/dist/features/seller/components/SellerProductShell.d.ts +19 -1
  305. package/dist/features/seller/components/SellerProductShell.js +75 -9
  306. package/dist/features/seller/components/SellerProductsView.js +10 -11
  307. package/dist/features/seller/components/SellerShippingView.js +3 -3
  308. package/dist/features/seller/components/SellerSidebar.js +10 -7
  309. package/dist/features/seller/components/SellerStorefrontView.js +3 -3
  310. package/dist/features/seller/schemas/index.d.ts +4 -4
  311. package/dist/features/shell/FormShell.js +2 -1
  312. package/dist/features/shell/QuickFormDrawer.js +4 -3
  313. package/dist/features/shell/StepForm.js +4 -3
  314. package/dist/features/stores/actions/store-query-actions.js +4 -3
  315. package/dist/features/stores/components/StoreAboutView.js +2 -1
  316. package/dist/features/stores/components/StoreAuctionsListing.js +43 -64
  317. package/dist/features/stores/components/StoreDetailLayoutView.js +2 -2
  318. package/dist/features/stores/components/StorePreOrdersListing.js +33 -57
  319. package/dist/features/stores/components/StoreProductsListing.js +16 -49
  320. package/dist/features/stores/components/StoresIndexListing.js +2 -2
  321. package/dist/features/stores/schemas/index.d.ts +2 -2
  322. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +8 -7
  323. package/dist/features/wishlist/hooks/useGuestWishlist.d.ts +5 -5
  324. package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +6 -6
  325. package/dist/features/wishlist/utils/guest-wishlist.d.ts +5 -5
  326. package/dist/index.d.ts +21 -3
  327. package/dist/index.js +1737 -1725
  328. package/dist/monitoring/server-logger.js +5 -9
  329. package/dist/next/api/apiHandler.js +56 -37
  330. package/dist/next/components/GlobalError.js +2 -1
  331. package/dist/next/routing/route-map.d.ts +27 -0
  332. package/dist/next/routing/route-map.js +10 -0
  333. package/dist/react/ErrorBoundary.js +2 -1
  334. package/dist/react/contexts/SessionContext.js +38 -28
  335. package/dist/react/hooks/useCamera.d.ts +1 -1
  336. package/dist/react/hooks/useCamera.js +8 -7
  337. package/dist/seed/site-settings-seed-data.js +6 -0
  338. package/dist/server-entry.d.ts +3 -0
  339. package/dist/server-entry.js +3 -0
  340. package/dist/server.d.ts +12 -0
  341. package/dist/server.js +15 -0
  342. package/dist/tailwind-utilities.css +1 -1
  343. package/dist/ui/DataTable.js +28 -7
  344. package/dist/ui/components/Button.d.ts +8 -1
  345. package/dist/ui/components/Button.js +47 -8
  346. package/dist/ui/components/CollageLightbox.d.ts +18 -0
  347. package/dist/ui/components/CollageLightbox.js +41 -0
  348. package/dist/ui/components/Dropdown.js +7 -6
  349. package/dist/ui/components/ImageLightbox.d.ts +7 -1
  350. package/dist/ui/components/ImageLightbox.js +15 -5
  351. package/dist/ui/components/PageLoader.js +4 -3
  352. package/dist/ui/components/PaginatedMultiSelect.d.ts +28 -0
  353. package/dist/ui/components/PaginatedMultiSelect.js +141 -0
  354. package/dist/ui/components/PaginatedMultiSelect.style.css +272 -0
  355. package/dist/ui/components/Semantic.js +1 -1
  356. package/dist/ui/components/SideDrawer.js +17 -15
  357. package/dist/ui/components/index.style.css +1 -0
  358. package/dist/ui/index.d.ts +2 -0
  359. package/dist/ui/index.js +1 -0
  360. package/dist/utils/number.formatter.js +5 -13
  361. package/dist/utils/string.formatter.js +21 -18
  362. package/dist/validation/schemas.d.ts +2 -2
  363. package/package.json +2 -2
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
+ import { useCallback, useEffect, useRef, useState } from "react";
4
4
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
5
5
  import { Main, Div, Text, TextLink, Ul, Li, AvatarDisplay, BackgroundRenderer, UnsavedChangesModal, } from "../../ui";
6
6
  const ROLE_DOT_COLORS = {
@@ -11,14 +11,12 @@ const ROLE_DOT_COLORS = {
11
11
  };
12
12
  import { useTheme } from "../../react";
13
13
  import { useAuth } from "../../react/contexts/SessionContext";
14
- import { useSiteSettings } from "../../core/hooks/useSiteSettings";
15
- import { filterNavItems } from "../../_internal/client/features/layout/filterNavItems";
14
+ import { NavbarWithSettings } from "./NavbarWithSettings";
16
15
  import { useBottomActionsContext } from "./BottomActionsContext";
17
16
  import BottomActions from "./BottomActions";
18
17
  import { AutoBreadcrumbs } from "./AutoBreadcrumbs";
19
18
  import { BottomNavbar } from "./BottomNavbar";
20
19
  import { FooterLayout } from "./FooterLayout";
21
- import { MainNavbar } from "./MainNavbar";
22
20
  import { SidebarLayout } from "./SidebarLayout";
23
21
  import { TitleBar } from "./TitleBar";
24
22
  import { BackToTop } from "./BackToTop";
@@ -28,6 +26,8 @@ const DEFAULT_LIGHT_BG = {
28
26
  value: "#f9fafb",
29
27
  overlay: { enabled: false, color: "#000000", opacity: 0 },
30
28
  };
29
+ const CLS_STAT_BOX = "flex flex-col items-center gap-1 p-2 bg-zinc-100 dark:bg-zinc-800 rounded-lg text-center";
30
+ const CLS_STAT_LABEL = "text-xs text-zinc-500 dark:text-zinc-400";
31
31
  const DEFAULT_DARK_BG = {
32
32
  type: "color",
33
33
  value: "#030712",
@@ -46,7 +46,55 @@ function CollapsibleSidebarSection({ section, navItemClass, }) {
46
46
  }
47
47
  return (_jsxs(Div, { className: "space-y-0.5", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "flex w-full items-center justify-between px-1 py-1 text-xs font-semibold uppercase tracking-wider text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-300 transition-colors", children: [_jsx("span", { children: section.title }), _jsx("svg", { className: `w-3.5 h-3.5 transition-transform duration-200 ${open ? "rotate-180" : ""}`, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) })] }), open && (_jsx(Ul, { className: "space-y-0.5", children: section.items.map((item) => (_jsx(Li, { children: _jsxs(TextLink, { href: item.href, variant: "none", className: navItemClass, children: [item.icon && (_jsx("span", { className: "flex-shrink-0 w-5 text-center", "aria-hidden": "true", children: item.icon })), item.label] }) }, `${item.href}-${item.label}`))) }))] }));
48
48
  }
49
- export function AppLayoutShell({ children, navItems, sidebarItems = [], sidebarSections, sidebarPrimaryActions, sidebarTitle = "Navigation", hiddenNavItems, user, brandName, brandShortName, siteLogoUrl, logoHref, promotionsHref, cartHref, wishlistHref, userId, profileHref, loginHref, registerHref, homeHref, shopHref, footer, searchSlot, searchSlotRenderer, titleBarNavSlot, titleBarNotificationSlot, titleBarDevSlot, titleBarPromoStripText, showThemeToggle = false, suppressDashboardNav = false, hideSidebarToggle = false, onLogout, adminHref, storeHref, sellerHref, userOrdersHref, userWishlistHref, userSettingsHref, sidebarLocaleSlot, showThemeToggleInSidebar = false, sidebarProfileLabels, eventBannerSlot, lightBackground = DEFAULT_LIGHT_BG, darkBackground = DEFAULT_DARK_BG, }) {
49
+ /** Sidebar header when a user is logged in avatar + display name + close button. */
50
+ function SidebarUserHeader({ user, onClose, }) {
51
+ return (_jsxs(Div, { className: "flex items-center justify-between gap-3", children: [_jsxs(Div, { className: "flex items-center gap-3 flex-1 min-w-0", children: [_jsxs(Div, { className: "flex-shrink-0 relative", children: [_jsx(AvatarDisplay, { cropData: user.avatarMetadata
52
+ ? {
53
+ url: user.avatarMetadata.url,
54
+ position: user.avatarMetadata.position ?? { x: 50, y: 50 },
55
+ zoom: user.avatarMetadata.zoom ?? 1,
56
+ }
57
+ : user.photoURL
58
+ ? { url: user.photoURL, position: { x: 50, y: 50 }, zoom: 1 }
59
+ : null, size: "md", alt: user.displayName || "User", displayName: user.displayName, email: user.email }), user.role && user.role !== "user" && (_jsx(Div, { className: "absolute -bottom-0.5 -right-0.5 flex items-center justify-center w-4 h-4 rounded-full border-2 border-white dark:border-slate-900 text-white text-[9px] font-bold leading-none select-none", style: { background: ROLE_DOT_COLORS[user.role] ?? "#6b7280" }, title: user.role.charAt(0).toUpperCase() + user.role.slice(1), "aria-label": user.role, children: user.role.charAt(0).toUpperCase() }))] }), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Text, { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100 truncate", children: user.displayName || "User" }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 truncate", children: user.email || "" })] })] }), _jsx("button", { type: "button", "aria-label": "Close menu", onClick: onClose, className: "flex-shrink-0 rounded-full p-2 text-zinc-600 hover:bg-zinc-200 hover:text-zinc-900 dark:text-zinc-300 dark:hover:bg-slate-800 dark:hover:text-zinc-100 transition-all hover:rotate-90", children: _jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }));
60
+ }
61
+ /** Sidebar header when no user is logged in — title + close button. */
62
+ function SidebarGuestHeader({ sidebarTitle, onClose, }) {
63
+ return (_jsxs(Div, { className: "flex items-center justify-between", children: [_jsx(Div, { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: sidebarTitle }), _jsx("button", { type: "button", "aria-label": "Close menu", onClick: onClose, className: "rounded-full p-2 text-zinc-600 hover:bg-zinc-200 hover:text-zinc-900 dark:text-zinc-300 dark:hover:bg-slate-800 dark:hover:text-zinc-100 transition-all hover:rotate-90", children: _jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }));
64
+ }
65
+ function SidebarContent({ sidebarItems, sidebarSections, sidebarPrimaryActions, user, profileHref, userOrdersHref, userWishlistHref, userSettingsHref, adminHref, storeHref, sellerHref, sidebarLocaleSlot, showThemeToggleInSidebar, sidebarProfileLabels, theme, toggleTheme, onLogout, onAfterLogout, }) {
66
+ const hasLegacyItems = sidebarItems.length > 0;
67
+ const hasSections = !!(sidebarSections && sidebarSections.length > 0);
68
+ const isAuthenticated = !!user;
69
+ const role = user?.role ?? "user";
70
+ const isAdminOrSeller = role === "admin" || role === "seller";
71
+ const resolvedStoreHref = storeHref ?? sellerHref;
72
+ const labels = {
73
+ sectionTitle: sidebarProfileLabels?.sectionTitle ?? "Profile",
74
+ profile: sidebarProfileLabels?.profile ?? "My Profile",
75
+ orders: sidebarProfileLabels?.orders ?? "My Orders",
76
+ wishlist: sidebarProfileLabels?.wishlist ?? "My Wishlist",
77
+ settings: sidebarProfileLabels?.settings ?? "Settings",
78
+ dashboardSectionTitle: sidebarProfileLabels?.dashboardSectionTitle ?? "Dashboard",
79
+ adminDashboard: sidebarProfileLabels?.adminDashboard ?? "Admin Dashboard",
80
+ storeDashboard: sidebarProfileLabels?.storeDashboard ?? sidebarProfileLabels?.sellerDashboard ?? "Store Dashboard",
81
+ logout: sidebarProfileLabels?.logout ?? "Logout",
82
+ };
83
+ const navItemClass = "flex items-center gap-2 rounded-lg px-3 py-2 text-sm text-zinc-700 transition-colors hover:bg-primary-50 hover:text-primary-800 dark:text-zinc-300 dark:hover:bg-slate-800 dark:hover:text-secondary-300";
84
+ const normalizedSections = hasSections
85
+ ? sidebarSections
86
+ : hasLegacyItems
87
+ ? [{ items: sidebarItems }]
88
+ : [];
89
+ return (_jsxs(Div, { className: "space-y-6", children: [!isAuthenticated && sidebarPrimaryActions && sidebarPrimaryActions.length > 0 && (_jsx(Div, { className: "space-y-2", children: sidebarPrimaryActions.map((action) => (_jsx(TextLink, { href: action.href, variant: "none", className: [
90
+ "block w-full rounded-lg px-3 py-2.5 text-center text-sm font-semibold transition-all duration-200 hover:scale-[1.02] shadow-sm",
91
+ action.variant === "outline"
92
+ ? "border border-zinc-300 text-zinc-700 hover:bg-zinc-50 dark:border-slate-700 dark:text-zinc-100 dark:hover:bg-slate-800"
93
+ : "bg-primary text-white hover:bg-primary-600 dark:bg-primary dark:hover:bg-primary-600 btn-glow",
94
+ ].join(" "), children: action.label }, `${action.href}-${action.label}`))) })), isAuthenticated && (_jsx(CollapsibleNavGroup, { title: labels.sectionTitle, children: _jsxs(Ul, { className: "space-y-0.5", children: [_jsx(Li, { children: _jsx(TextLink, { href: profileHref, variant: "none", className: navItemClass, children: labels.profile }) }), userOrdersHref && (_jsx(Li, { children: _jsx(TextLink, { href: userOrdersHref, variant: "none", className: navItemClass, children: labels.orders }) })), userWishlistHref && (_jsx(Li, { children: _jsx(TextLink, { href: userWishlistHref, variant: "none", className: navItemClass, children: labels.wishlist }) })), userSettingsHref && (_jsx(Li, { children: _jsx(TextLink, { href: userSettingsHref, variant: "none", className: navItemClass, children: labels.settings }) }))] }) })), isAuthenticated && user?.stats && (_jsxs(Div, { className: "grid grid-cols-2 gap-2", children: [user.stats.totalOrders != null && (_jsxs(Div, { className: CLS_STAT_BOX, children: [_jsx(Text, { className: "text-lg font-bold text-zinc-900 dark:text-zinc-100 leading-none", children: user.stats.totalOrders }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Orders" })] })), user.stats.reviewsCount != null && (_jsxs(Div, { className: CLS_STAT_BOX, children: [_jsx(Text, { className: "text-lg font-bold text-zinc-900 dark:text-zinc-100 leading-none", children: user.stats.reviewsCount }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Reviews" })] })), user.stats.auctionsWon != null && (_jsxs(Div, { className: CLS_STAT_BOX, children: [_jsx(Text, { className: "text-lg font-bold text-zinc-900 dark:text-zinc-100 leading-none", children: user.stats.auctionsWon }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Auctions Won" })] })), user.stats.itemsSold != null && (_jsxs(Div, { className: CLS_STAT_BOX, children: [_jsx(Text, { className: "text-lg font-bold text-zinc-900 dark:text-zinc-100 leading-none", children: user.stats.itemsSold }), _jsx(Text, { className: CLS_STAT_LABEL, children: "Items Sold" })] }))] })), isAuthenticated && isAdminOrSeller && (adminHref || resolvedStoreHref) && (_jsx(CollapsibleNavGroup, { title: labels.dashboardSectionTitle, children: _jsxs(Ul, { className: "space-y-0.5", children: [adminHref && role === "admin" && (_jsx(Li, { children: _jsx(TextLink, { href: adminHref, variant: "none", className: navItemClass, children: labels.adminDashboard }) })), resolvedStoreHref && isAdminOrSeller && (_jsx(Li, { children: _jsx(TextLink, { href: resolvedStoreHref, variant: "none", className: navItemClass, children: labels.storeDashboard }) }))] }) })), normalizedSections.map((section, sectionIndex) => (_jsx(CollapsibleSidebarSection, { section: section, navItemClass: navItemClass }, `sidebar-section-${sectionIndex}`))), (sidebarLocaleSlot || showThemeToggleInSidebar || (isAuthenticated && onLogout)) && (_jsxs(Div, { className: "border-t border-zinc-200 pt-4 space-y-3 dark:border-slate-800", children: [sidebarLocaleSlot, showThemeToggleInSidebar && (_jsxs("button", { type: "button", onClick: toggleTheme, className: "flex w-full items-center gap-3 rounded-lg px-3 py-2 text-sm text-zinc-700 transition-colors hover:bg-primary-50 hover:text-primary-800 dark:text-zinc-300 dark:hover:bg-slate-800 dark:hover:text-secondary-300", children: [_jsx("span", { "aria-hidden": "true", children: theme === "dark" ? "☀️" : "🌙" }), theme === "dark" ? "Light mode" : "Dark mode"] })), isAuthenticated && onLogout && (_jsx("button", { type: "button", onClick: () => { onLogout(); onAfterLogout(); }, className: "flex w-full items-center gap-3 rounded-lg px-3 py-2 text-sm text-red-600 transition-colors hover:bg-red-50 hover:text-red-700 dark:text-red-400 dark:hover:bg-red-950/30 dark:hover:text-red-300", children: labels.logout }))] }))] }));
95
+ }
96
+ // ─── Main component ────────────────────────────────────────────────────────────
97
+ export function AppLayoutShell({ children, navItems, sidebarItems = [], sidebarSections, sidebarPrimaryActions, sidebarTitle = "Navigation", hiddenNavItems, user, brandName, brandShortName, siteLogoUrl, logoHref, promotionsHref, cartHref, wishlistHref, userId, profileHref, loginHref, registerHref, homeHref, shopHref, footer, searchSlot, searchSlotRenderer, titleBarNavSlot, titleBarNotificationSlot, titleBarDevSlot, titleBarPromoStripText, showThemeToggle = false, suppressDashboardNav = false, hideSidebarToggle = false, onLogout, adminHref, storeHref, sellerHref, userOrdersHref, userWishlistHref, userSettingsHref, sidebarLocaleSlot, showThemeToggleInSidebar = false, sidebarProfileLabels, eventBannerSlot, contentClassName, lightBackground = DEFAULT_LIGHT_BG, darkBackground = DEFAULT_DARK_BG, }) {
50
98
  const [queryClient] = useState(() => new QueryClient());
51
99
  const [sidebarOpen, setSidebarOpen] = useState(false);
52
100
  const [searchOpen, setSearchOpen] = useState(false);
@@ -54,9 +102,6 @@ export function AppLayoutShell({ children, navItems, sidebarItems = [], sidebarS
54
102
  const { closeNav: closeDashboardNav, hasNav: hasDashboardNav, toggleNav: toggleDashboardNav } = useDashboardNav();
55
103
  const { state: bottomActionsState } = useBottomActionsContext();
56
104
  const { user: authUser } = useAuth();
57
- const { data: siteSettingsData } = useSiteSettings();
58
- const navConfig = siteSettingsData?.navConfig;
59
- const visibleNavItems = filterNavItems(navItems, navConfig, authUser?.permissions);
60
105
  const headerRef = useRef(null);
61
106
  useEffect(() => {
62
107
  const el = headerRef.current;
@@ -83,66 +128,7 @@ export function AppLayoutShell({ children, navItems, sidebarItems = [], sidebarS
83
128
  const hasBottomActions = bottomActionsState.actions.length > 0 ||
84
129
  !!(bottomActionsState.bulk && bottomActionsState.bulk.selectedCount > 0) ||
85
130
  !!bottomActionsState.infoLabel;
86
- const sidebarContent = useMemo(() => {
87
- const hasLegacyItems = sidebarItems.length > 0;
88
- const hasSections = !!(sidebarSections && sidebarSections.length > 0);
89
- const isAuthenticated = !!user;
90
- const role = user?.role ?? "user";
91
- const isAdminOrSeller = role === "admin" || role === "seller";
92
- const resolvedStoreHref = storeHref ?? sellerHref;
93
- // Labels with defaults
94
- const labels = {
95
- sectionTitle: sidebarProfileLabels?.sectionTitle ?? "Profile",
96
- profile: sidebarProfileLabels?.profile ?? "My Profile",
97
- orders: sidebarProfileLabels?.orders ?? "My Orders",
98
- wishlist: sidebarProfileLabels?.wishlist ?? "My Wishlist",
99
- settings: sidebarProfileLabels?.settings ?? "Settings",
100
- dashboardSectionTitle: sidebarProfileLabels?.dashboardSectionTitle ?? "Dashboard",
101
- adminDashboard: sidebarProfileLabels?.adminDashboard ?? "Admin Dashboard",
102
- storeDashboard: sidebarProfileLabels?.storeDashboard ??
103
- sidebarProfileLabels?.sellerDashboard ??
104
- "Store Dashboard",
105
- logout: sidebarProfileLabels?.logout ?? "Logout",
106
- };
107
- const sectionLabelClass = "px-1 text-xs font-semibold uppercase tracking-wider text-zinc-500 dark:text-zinc-400";
108
- const navItemClass = "flex items-center gap-2 rounded-lg px-3 py-2 text-sm text-zinc-700 transition-colors hover:bg-primary-50 hover:text-primary-800 dark:text-zinc-300 dark:hover:bg-slate-800 dark:hover:text-secondary-300";
109
- const normalizedSections = hasSections
110
- ? sidebarSections
111
- : hasLegacyItems
112
- ? [{ items: sidebarItems }]
113
- : [];
114
- return (_jsxs(Div, { className: "space-y-6", children: [!isAuthenticated &&
115
- sidebarPrimaryActions &&
116
- sidebarPrimaryActions.length > 0 && (_jsx(Div, { className: "space-y-2", children: sidebarPrimaryActions.map((action) => (_jsx(TextLink, { href: action.href, variant: "none", className: [
117
- "block w-full rounded-lg px-3 py-2.5 text-center text-sm font-semibold transition-all duration-200 hover:scale-[1.02] shadow-sm",
118
- action.variant === "outline"
119
- ? "border border-zinc-300 text-zinc-700 hover:bg-zinc-50 dark:border-slate-700 dark:text-zinc-100 dark:hover:bg-slate-800"
120
- : "bg-primary text-white hover:bg-primary-600 dark:bg-primary dark:hover:bg-primary-600 btn-glow",
121
- ].join(" "), children: action.label }, `${action.href}-${action.label}`))) })), isAuthenticated && (_jsx(CollapsibleNavGroup, { title: labels.sectionTitle, children: _jsxs(Ul, { className: "space-y-0.5", children: [_jsx(Li, { children: _jsx(TextLink, { href: profileHref, variant: "none", className: navItemClass, children: labels.profile }) }), userOrdersHref && (_jsx(Li, { children: _jsx(TextLink, { href: userOrdersHref, variant: "none", className: navItemClass, children: labels.orders }) })), userWishlistHref && (_jsx(Li, { children: _jsx(TextLink, { href: userWishlistHref, variant: "none", className: navItemClass, children: labels.wishlist }) })), userSettingsHref && (_jsx(Li, { children: _jsx(TextLink, { href: userSettingsHref, variant: "none", className: navItemClass, children: labels.settings }) }))] }) })), isAuthenticated && user?.stats && (_jsxs(Div, { className: "grid grid-cols-2 gap-2", children: [user.stats.totalOrders != null && (_jsxs(Div, { className: "rounded-lg bg-zinc-100 dark:bg-slate-800 px-3 py-2.5 text-center", children: [_jsx(Text, { className: "text-lg font-bold text-zinc-900 dark:text-zinc-100 leading-none", children: user.stats.totalOrders }), _jsx(Text, { className: "mt-0.5 text-[11px] text-zinc-500 dark:text-zinc-400", children: "Orders" })] })), user.stats.reviewsCount != null && (_jsxs(Div, { className: "rounded-lg bg-zinc-100 dark:bg-slate-800 px-3 py-2.5 text-center", children: [_jsx(Text, { className: "text-lg font-bold text-zinc-900 dark:text-zinc-100 leading-none", children: user.stats.reviewsCount }), _jsx(Text, { className: "mt-0.5 text-[11px] text-zinc-500 dark:text-zinc-400", children: "Reviews" })] })), user.stats.auctionsWon != null && (_jsxs(Div, { className: "rounded-lg bg-zinc-100 dark:bg-slate-800 px-3 py-2.5 text-center", children: [_jsx(Text, { className: "text-lg font-bold text-zinc-900 dark:text-zinc-100 leading-none", children: user.stats.auctionsWon }), _jsx(Text, { className: "mt-0.5 text-[11px] text-zinc-500 dark:text-zinc-400", children: "Auctions Won" })] })), user.stats.itemsSold != null && (_jsxs(Div, { className: "rounded-lg bg-zinc-100 dark:bg-slate-800 px-3 py-2.5 text-center", children: [_jsx(Text, { className: "text-lg font-bold text-zinc-900 dark:text-zinc-100 leading-none", children: user.stats.itemsSold }), _jsx(Text, { className: "mt-0.5 text-[11px] text-zinc-500 dark:text-zinc-400", children: "Items Sold" })] }))] })), isAuthenticated && isAdminOrSeller && (adminHref || resolvedStoreHref) && (_jsx(CollapsibleNavGroup, { title: labels.dashboardSectionTitle, children: _jsxs(Ul, { className: "space-y-0.5", children: [adminHref && role === "admin" && (_jsx(Li, { children: _jsx(TextLink, { href: adminHref, variant: "none", className: navItemClass, children: labels.adminDashboard }) })), resolvedStoreHref && isAdminOrSeller && (_jsx(Li, { children: _jsx(TextLink, { href: resolvedStoreHref, variant: "none", className: navItemClass, children: labels.storeDashboard }) }))] }) })), normalizedSections.map((section, sectionIndex) => (_jsx(CollapsibleSidebarSection, { section: section, navItemClass: navItemClass }, `sidebar-section-${sectionIndex}`))), (sidebarLocaleSlot ||
122
- showThemeToggleInSidebar ||
123
- (isAuthenticated && onLogout)) && (_jsxs(Div, { className: "border-t border-zinc-200 pt-4 space-y-3 dark:border-slate-800", children: [sidebarLocaleSlot, showThemeToggleInSidebar && (_jsxs("button", { type: "button", onClick: toggleTheme, className: "flex w-full items-center gap-3 rounded-lg px-3 py-2 text-sm text-zinc-700 transition-colors hover:bg-primary-50 hover:text-primary-800 dark:text-zinc-300 dark:hover:bg-slate-800 dark:hover:text-secondary-300", children: [_jsx("span", { "aria-hidden": "true", children: theme === "dark" ? "☀️" : "🌙" }), theme === "dark" ? "Light mode" : "Dark mode"] })), isAuthenticated && onLogout && (_jsx("button", { type: "button", onClick: () => {
124
- onLogout();
125
- setSidebarOpen(false);
126
- }, className: "flex w-full items-center gap-3 rounded-lg px-3 py-2 text-sm text-red-600 transition-colors hover:bg-red-50 hover:text-red-700 dark:text-red-400 dark:hover:bg-red-950/30 dark:hover:text-red-300", children: labels.logout }))] }))] }));
127
- }, [
128
- sidebarItems,
129
- sidebarSections,
130
- sidebarPrimaryActions,
131
- user,
132
- profileHref,
133
- userOrdersHref,
134
- userWishlistHref,
135
- userSettingsHref,
136
- adminHref,
137
- storeHref,
138
- sellerHref,
139
- sidebarLocaleSlot,
140
- showThemeToggleInSidebar,
141
- onLogout,
142
- sidebarProfileLabels,
143
- theme,
144
- toggleTheme,
145
- ]);
131
+ const sidebarContent = (_jsx(SidebarContent, { sidebarItems: sidebarItems, sidebarSections: sidebarSections, sidebarPrimaryActions: sidebarPrimaryActions, user: user, profileHref: profileHref, userOrdersHref: userOrdersHref, userWishlistHref: userWishlistHref, userSettingsHref: userSettingsHref, adminHref: adminHref, storeHref: storeHref, sellerHref: sellerHref, sidebarLocaleSlot: sidebarLocaleSlot, showThemeToggleInSidebar: showThemeToggleInSidebar, sidebarProfileLabels: sidebarProfileLabels, theme: theme, toggleTheme: toggleTheme, onLogout: onLogout, onAfterLogout: () => setSidebarOpen(false) }));
146
132
  const normalizedLightBackground = {
147
133
  type: lightBackground.type,
148
134
  value: lightBackground.value,
@@ -161,20 +147,5 @@ export function AppLayoutShell({ children, navItems, sidebarItems = [], sidebarS
161
147
  opacity: darkBackground.overlay?.opacity ?? 0,
162
148
  },
163
149
  };
164
- return (_jsx(QueryClientProvider, { client: queryClient, children: _jsxs(Div, { className: "flex min-h-screen w-full flex-col overflow-x-clip transition-colors duration-300", children: [_jsx(BackgroundRenderer, { mode: theme === "dark" ? "dark" : "light", lightMode: normalizedLightBackground, darkMode: normalizedDarkBackground }), _jsxs(Div, { ref: headerRef, className: "sticky top-0 z-50 w-full", children: [_jsx(TitleBar, { onToggleSidebar: handleTogglePublicSidebar, sidebarOpen: sidebarOpen, onSearchToggle: () => setSearchOpen((prev) => !prev), searchOpen: searchOpen, brandName: brandName, brandShortName: brandShortName, siteLogoUrl: siteLogoUrl, logoHref: logoHref, promotionsHref: promotionsHref, cartHref: cartHref, wishlistHref: wishlistHref, userId: userId, profileHref: profileHref, loginHref: loginHref, registerHref: registerHref, user: user, navSlot: titleBarNavSlot, notificationSlot: titleBarNotificationSlot, devSlot: titleBarDevSlot, promoStripText: titleBarPromoStripText, isDark: theme === "dark", onToggleTheme: showThemeToggle ? toggleTheme : undefined, onBeforeToggleDashboardNav: handleBeforeDashboardNavToggle, suppressDashboardNav: suppressDashboardNav, hideSidebarToggle: hideSidebarToggle }), _jsx(MainNavbar, { navItems: visibleNavItems, hiddenNavItems: hiddenNavItems }), searchOpen && (searchSlotRenderer ? searchSlotRenderer(() => setSearchOpen(false)) : searchSlot)] }), eventBannerSlot, _jsx(AutoBreadcrumbs, {}), _jsxs(Div, { className: "relative flex w-full flex-1 overflow-x-clip", children: [_jsx(SidebarLayout, { isOpen: sidebarOpen, ariaLabel: "Secondary navigation", header: user ? (_jsxs(Div, { className: "flex items-center justify-between gap-3", children: [_jsxs(Div, { className: "flex items-center gap-3 flex-1 min-w-0", children: [_jsxs(Div, { className: "flex-shrink-0 relative", children: [_jsx(AvatarDisplay, { cropData: user.avatarMetadata
165
- ? {
166
- url: user.avatarMetadata.url,
167
- position: user.avatarMetadata.position ?? {
168
- x: 50,
169
- y: 50,
170
- },
171
- zoom: user.avatarMetadata.zoom ?? 1,
172
- }
173
- : user.photoURL
174
- ? {
175
- url: user.photoURL,
176
- position: { x: 50, y: 50 },
177
- zoom: 1,
178
- }
179
- : null, size: "md", alt: user.displayName || "User", displayName: user.displayName, email: user.email }), user.role && user.role !== "user" && (_jsx(Div, { className: "absolute -bottom-0.5 -right-0.5 flex items-center justify-center w-4 h-4 rounded-full border-2 border-white dark:border-slate-900 text-white text-[9px] font-bold leading-none select-none", style: { background: ROLE_DOT_COLORS[user.role] ?? "#6b7280" }, title: user.role.charAt(0).toUpperCase() + user.role.slice(1), "aria-label": user.role, children: user.role.charAt(0).toUpperCase() }))] }), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsx(Text, { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100 truncate", children: user.displayName || "User" }), _jsx(Text, { className: "text-xs text-zinc-500 dark:text-zinc-400 truncate", children: user.email || "" })] })] }), _jsx("button", { type: "button", "aria-label": "Close menu", onClick: () => setSidebarOpen(false), className: "flex-shrink-0 rounded-full p-2 text-zinc-600 hover:bg-zinc-200 hover:text-zinc-900 dark:text-zinc-300 dark:hover:bg-slate-800 dark:hover:text-zinc-100 transition-all hover:rotate-90", children: _jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] })) : (_jsxs(Div, { className: "flex items-center justify-between", children: [_jsx(Div, { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: sidebarTitle }), _jsx("button", { type: "button", "aria-label": "Close menu", onClick: () => setSidebarOpen(false), className: "rounded-full p-2 text-zinc-600 hover:bg-zinc-200 hover:text-zinc-900 dark:text-zinc-300 dark:hover:bg-slate-800 dark:hover:text-zinc-100 transition-all hover:rotate-90", children: _jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] })), onClose: () => setSidebarOpen(false), children: sidebarContent }), _jsx(Main, { id: "main-content", className: `w-full flex-1 ${hasBottomActions ? "mb-28" : "mb-16"} md:mb-0`, children: _jsx(Div, { className: "container mx-auto w-full max-w-screen-2xl px-4 py-6 md:px-6 lg:px-8", children: children }) })] }), _jsx(BackToTop, {}), _jsx(FooterLayout, { ...footer }), _jsx(BottomActions, {}), _jsx(BottomNavbar, { user: user, homeHref: homeHref, shopHref: shopHref, cartHref: cartHref, profileHref: profileHref, loginHref: loginHref, onSearchToggle: () => setSearchOpen((prev) => !prev), navItems: navItems, onMoreToggle: hasDashboardNav ? toggleDashboardNav : handleTogglePublicSidebar }), _jsx(UnsavedChangesModal, {})] }) }));
150
+ return (_jsx(QueryClientProvider, { client: queryClient, children: _jsxs(Div, { className: "flex min-h-screen w-full flex-col overflow-x-clip transition-colors duration-300", children: [_jsx(BackgroundRenderer, { mode: theme === "dark" ? "dark" : "light", lightMode: normalizedLightBackground, darkMode: normalizedDarkBackground }), _jsxs(Div, { ref: headerRef, className: "sticky top-0 z-50 w-full", children: [_jsx(TitleBar, { onToggleSidebar: handleTogglePublicSidebar, sidebarOpen: sidebarOpen, onSearchToggle: () => setSearchOpen((prev) => !prev), searchOpen: searchOpen, brandName: brandName, brandShortName: brandShortName, siteLogoUrl: siteLogoUrl, logoHref: logoHref, promotionsHref: promotionsHref, cartHref: cartHref, wishlistHref: wishlistHref, userId: userId, profileHref: profileHref, loginHref: loginHref, registerHref: registerHref, user: user, navSlot: titleBarNavSlot, notificationSlot: titleBarNotificationSlot, devSlot: titleBarDevSlot, promoStripText: titleBarPromoStripText, isDark: theme === "dark", onToggleTheme: showThemeToggle ? toggleTheme : undefined, onBeforeToggleDashboardNav: handleBeforeDashboardNavToggle, suppressDashboardNav: suppressDashboardNav, hideSidebarToggle: hideSidebarToggle }), _jsx(NavbarWithSettings, { navItems: navItems, hiddenNavItems: hiddenNavItems, permissions: authUser?.permissions }), searchOpen && (searchSlotRenderer ? searchSlotRenderer(() => setSearchOpen(false)) : searchSlot)] }), eventBannerSlot, _jsx(AutoBreadcrumbs, {}), _jsxs(Div, { className: "relative flex w-full flex-1 overflow-x-clip", children: [_jsx(SidebarLayout, { isOpen: sidebarOpen, ariaLabel: "Secondary navigation", header: user ? (_jsx(SidebarUserHeader, { user: user, onClose: () => setSidebarOpen(false) })) : (_jsx(SidebarGuestHeader, { sidebarTitle: sidebarTitle, onClose: () => setSidebarOpen(false) })), onClose: () => setSidebarOpen(false), children: sidebarContent }), _jsx(Main, { id: "main-content", className: `w-full flex-1 ${hasBottomActions ? "mb-28" : "mb-16"} md:mb-0`, children: _jsx(Div, { className: contentClassName ?? "container mx-auto w-full max-w-screen-2xl px-4 py-6 md:px-6 lg:px-8", children: children }) })] }), _jsx(BackToTop, {}), _jsx(FooterLayout, { ...footer }), _jsx(BottomActions, {}), _jsx(BottomNavbar, { user: user, homeHref: homeHref, shopHref: shopHref, cartHref: cartHref, profileHref: profileHref, loginHref: loginHref, onSearchToggle: () => setSearchOpen((prev) => !prev), navItems: navItems, onMoreToggle: hasDashboardNav ? toggleDashboardNav : handleTogglePublicSidebar }), _jsx(UnsavedChangesModal, {})] }) }));
180
151
  }
@@ -37,6 +37,47 @@ const BOTTOM_NAV_BG = "bg-white/90 dark:bg-slate-950/90 backdrop-blur-md border-
37
37
  const Z_BOTTOM_ACTIONS = "z-40";
38
38
  const BOTTOM_NAV_HEIGHT = "h-14";
39
39
  const FLEX_CENTER = "flex items-center justify-center";
40
+ // ─── Sub-components ───────────────────────────────────────────────────────────
41
+ function BulkPickerPanel({ bulkActions, selectedActionId, pickerOpen, onSelect, }) {
42
+ return (_jsx("div", { role: "listbox", "aria-label": "Bulk actions", className: [
43
+ "absolute bottom-full left-0 right-0 overflow-hidden",
44
+ BOTTOM_NAV_BG,
45
+ "border-t border-zinc-200/80 dark:border-slate-700/80",
46
+ "shadow-[0_-8px_24px_rgba(0,0,0,0.10)] dark:shadow-[0_-8px_24px_rgba(0,0,0,0.35)]",
47
+ "transition-[max-height,opacity] duration-200 ease-out",
48
+ pickerOpen ? "max-h-64 opacity-100" : "max-h-0 opacity-0 pointer-events-none",
49
+ ]
50
+ .filter(Boolean)
51
+ .join(" "), children: bulkActions.map((action, i) => {
52
+ const isSelected = action.id === selectedActionId;
53
+ return (_jsxs(Button, { role: "option", "aria-selected": isSelected, type: "button", variant: "ghost", disabled: action.disabled || action.loading, onClick: () => onSelect(action.id), className: [
54
+ "w-full flex items-center gap-3 px-5 py-3.5 text-left text-sm font-medium transition-colors rounded-none",
55
+ i > 0 ? "border-t border-zinc-100/80 dark:border-slate-800/80" : "",
56
+ isSelected ? "bg-zinc-50 dark:bg-slate-800/60" : "",
57
+ action.variant === "danger"
58
+ ? "text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-950/30"
59
+ : "text-zinc-800 dark:text-zinc-100 hover:bg-zinc-50 dark:hover:bg-slate-800/60",
60
+ action.disabled || action.loading ? "opacity-50 cursor-not-allowed" : "",
61
+ ]
62
+ .filter(Boolean)
63
+ .join(" "), children: [action.icon && (_jsx(Span, { className: `flex-shrink-0 w-5 h-5 ${FLEX_CENTER}`, "aria-hidden": "true", children: action.icon })), _jsx(Span, { className: "flex-1 truncate", children: action.label }), isSelected && (_jsx(Check, { className: "w-4 h-4 flex-shrink-0 text-primary-600 dark:text-primary-400", "aria-hidden": "true" }))] }, action.id));
64
+ }) }));
65
+ }
66
+ function PageActionsRow({ pageActions, dispatchAction, }) {
67
+ return (_jsx(_Fragment, { children: pageActions.map((action) => {
68
+ const isIconOnly = !action.label;
69
+ const growClass = isIconOnly || action.grow === false
70
+ ? "flex-shrink-0 w-11"
71
+ : "flex-1 min-w-0";
72
+ return (_jsxs(Button, { type: "button", variant: action.variant ?? "primary", size: "sm", isLoading: action.loading, disabled: action.disabled, onClick: () => dispatchAction(action.id), className: [
73
+ "h-10 relative",
74
+ growClass,
75
+ isIconOnly ? "px-0 justify-center" : "",
76
+ ]
77
+ .filter(Boolean)
78
+ .join(" "), children: [action.icon && (_jsx(Span, { className: ["flex-shrink-0", action.label ? "mr-1.5" : ""].join(" "), "aria-hidden": "true", children: action.icon })), action.label && _jsx(Span, { className: "truncate leading-none", children: action.label }), action.badge !== undefined && (_jsx(Span, { className: `absolute -top-1.5 -right-1.5 min-w-[18px] h-[18px] bg-red-500 text-white text-[10px] font-bold rounded-full ${FLEX_CENTER} px-1 pointer-events-none select-none`, "aria-hidden": "true", children: action.badge }))] }, action.id));
79
+ }) }));
80
+ }
40
81
  export default function BottomActions() {
41
82
  const { state, actionCallbacksRef, bulkCallbacksRef, bulkClearRef } = useBottomActionsContext();
42
83
  const [pickerOpen, setPickerOpen] = useState(false);
@@ -85,38 +126,7 @@ export default function BottomActions() {
85
126
  isVisible ? "translate-y-0" : "translate-y-full pointer-events-none",
86
127
  ]
87
128
  .filter(Boolean)
88
- .join(" "), "data-section": "bottomactions-div-401", children: [isBulkMode && (_jsx("div", { role: "listbox", "aria-label": "Bulk actions", className: [
89
- "absolute bottom-full left-0 right-0 overflow-hidden",
90
- BOTTOM_NAV_BG,
91
- "border-t border-zinc-200/80 dark:border-slate-700/80",
92
- "shadow-[0_-8px_24px_rgba(0,0,0,0.10)] dark:shadow-[0_-8px_24px_rgba(0,0,0,0.35)]",
93
- "transition-[max-height,opacity] duration-200 ease-out",
94
- pickerOpen
95
- ? "max-h-64 opacity-100"
96
- : "max-h-0 opacity-0 pointer-events-none",
97
- ]
98
- .filter(Boolean)
99
- .join(" "), "data-section": "bottomactions-div-402", children: bulkActions.map((action, i) => {
100
- const isSelected = action.id === selectedActionId;
101
- return (_jsxs(Button, { role: "option", "aria-selected": isSelected, type: "button", variant: "ghost", disabled: action.disabled || action.loading, onClick: () => {
102
- setSelectedActionId(action.id);
103
- setPickerOpen(false);
104
- }, className: [
105
- "w-full flex items-center gap-3 px-5 py-3.5 text-left text-sm font-medium transition-colors rounded-none",
106
- i > 0
107
- ? "border-t border-zinc-100/80 dark:border-slate-800/80"
108
- : "",
109
- isSelected ? "bg-zinc-50 dark:bg-slate-800/60" : "",
110
- action.variant === "danger"
111
- ? "text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-950/30"
112
- : "text-zinc-800 dark:text-zinc-100 hover:bg-zinc-50 dark:hover:bg-slate-800/60",
113
- action.disabled || action.loading
114
- ? "opacity-50 cursor-not-allowed"
115
- : "",
116
- ]
117
- .filter(Boolean)
118
- .join(" "), children: [action.icon && (_jsx(Span, { className: `flex-shrink-0 w-5 h-5 ${FLEX_CENTER}`, "aria-hidden": "true", children: action.icon })), _jsx(Span, { className: "flex-1 truncate", children: action.label }), isSelected && (_jsx(Check, { className: "w-4 h-4 flex-shrink-0 text-primary-600 dark:text-primary-400", "aria-hidden": "true" }))] }, action.id));
119
- }) })), isBulkMode && (_jsx("div", { className: "h-[3px] w-full bg-gradient-to-r from-primary-600 via-secondary-400 to-primary-600 dark:from-primary-600 dark:via-primary-400 dark:to-primary-600" })), infoLabel && !isBulkMode && (_jsx("div", { className: "px-4 pt-2 pb-0 border-b border-zinc-100/80 dark:border-slate-800/80", "data-section": "bottomactions-div-403", children: _jsx(Text, { className: "text-xs font-semibold text-zinc-500 dark:text-zinc-400 leading-5 truncate", children: infoLabel }) })), _jsx(Row, { className: `gap-2 px-3 ${BOTTOM_NAV_HEIGHT}`, children: isBulkMode && bulk ? (_jsxs(_Fragment, { children: [_jsxs(Button, { type: "button", variant: "ghost", onClick: dispatchBulkClear, className: "inline-flex items-center gap-1.5 flex-shrink-0 bg-primary-50 hover:bg-primary-100 active:bg-primary-200 dark:bg-primary-950/30 dark:hover:bg-primary-900/50 text-primary-700 dark:text-primary-300 rounded-full pl-2 pr-3 h-8 border border-primary-200/70 dark:border-primary-800/50 transition-colors min-h-0", "aria-label": "Clear selection", children: [_jsx(X, { className: "w-3.5 h-3.5 flex-shrink-0", "aria-hidden": "true" }), _jsx(Span, { className: "text-xs font-semibold tabular-nums whitespace-nowrap leading-none", children: bulk.noun
129
+ .join(" "), "data-section": "bottomactions-div-401", children: [isBulkMode && (_jsx(BulkPickerPanel, { bulkActions: bulkActions, selectedActionId: selectedActionId, pickerOpen: pickerOpen, onSelect: (id) => { setSelectedActionId(id); setPickerOpen(false); } })), isBulkMode && (_jsx("div", { className: "h-[3px] w-full bg-gradient-to-r from-primary-600 via-secondary-400 to-primary-600 dark:from-primary-600 dark:via-primary-400 dark:to-primary-600" })), infoLabel && !isBulkMode && (_jsx("div", { className: "px-4 pt-2 pb-0 border-b border-zinc-100/80 dark:border-slate-800/80", "data-section": "bottomactions-div-403", children: _jsx(Text, { className: "text-xs font-semibold text-zinc-500 dark:text-zinc-400 leading-5 truncate", children: infoLabel }) })), _jsx(Row, { className: `gap-2 px-3 ${BOTTOM_NAV_HEIGHT}`, children: isBulkMode && bulk ? (_jsxs(_Fragment, { children: [_jsxs(Button, { type: "button", variant: "ghost", onClick: dispatchBulkClear, className: "inline-flex items-center gap-1.5 flex-shrink-0 bg-primary-50 hover:bg-primary-100 active:bg-primary-200 dark:bg-primary-950/30 dark:hover:bg-primary-900/50 text-primary-700 dark:text-primary-300 rounded-full pl-2 pr-3 h-8 border border-primary-200/70 dark:border-primary-800/50 transition-colors min-h-0", "aria-label": "Clear selection", children: [_jsx(X, { className: "w-3.5 h-3.5 flex-shrink-0", "aria-hidden": "true" }), _jsx(Span, { className: "text-xs font-semibold tabular-nums whitespace-nowrap leading-none", children: bulk.noun
120
130
  ? `${bulk.selectedCount} ${bulk.noun}`
121
131
  : `${bulk.selectedCount} selected` })] }), bulkActions.length > 0 && (_jsxs(Button, { type: "button", variant: "ghost", onClick: () => setPickerOpen((o) => !o), "aria-haspopup": "listbox", "aria-expanded": pickerOpen, className: [
122
132
  "flex-1 min-w-0 h-10 flex items-center gap-2 px-3 rounded-lg border text-sm font-medium transition-colors",
@@ -131,20 +141,5 @@ export default function BottomActions() {
131
141
  selectedAction?.disabled ||
132
142
  selectedAction?.loading, onClick: handleApply, className: "h-10 flex-shrink-0", children: _jsx(Span, { className: "leading-none", children: "Apply" }) }))] })) : (
133
143
  /* Page mode — action buttons inline ------------------------------ */
134
- pageActions.map((action) => {
135
- const isIconOnly = !action.label;
136
- const growClass = isIconOnly || action.grow === false
137
- ? "flex-shrink-0 w-11"
138
- : "flex-1 min-w-0";
139
- return (_jsxs(Button, { type: "button", variant: action.variant ?? "primary", size: "sm", isLoading: action.loading, disabled: action.disabled, onClick: () => dispatchAction(action.id), className: [
140
- "h-10 relative",
141
- growClass,
142
- isIconOnly ? "px-0 justify-center" : "",
143
- ]
144
- .filter(Boolean)
145
- .join(" "), children: [action.icon && (_jsx(Span, { className: [
146
- "flex-shrink-0",
147
- action.label ? "mr-1.5" : "",
148
- ].join(" "), "aria-hidden": "true", children: action.icon })), action.label && (_jsx(Span, { className: "truncate leading-none", children: action.label })), action.badge !== undefined && (_jsx(Span, { className: `absolute -top-1.5 -right-1.5 min-w-[18px] h-[18px] bg-red-500 text-white text-[10px] font-bold rounded-full ${FLEX_CENTER} px-1 pointer-events-none select-none`, "aria-hidden": "true", children: action.badge }))] }, action.id));
149
- })) })] }));
144
+ _jsx(PageActionsRow, { pageActions: pageActions, dispatchAction: dispatchAction })) })] }));
150
145
  }
@@ -0,0 +1,6 @@
1
+ import { type MainNavbarItem } from "./MainNavbar";
2
+ export declare function NavbarWithSettings({ navItems, hiddenNavItems, permissions, }: {
3
+ navItems: MainNavbarItem[];
4
+ hiddenNavItems?: string[];
5
+ permissions?: string[];
6
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,11 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { useSiteSettings } from "../../core/hooks/useSiteSettings";
4
+ import { filterNavItems } from "../../_internal/client/features/layout/filterNavItems";
5
+ import { MainNavbar } from "./MainNavbar";
6
+ export function NavbarWithSettings({ navItems, hiddenNavItems, permissions, }) {
7
+ const { data: siteSettingsData } = useSiteSettings();
8
+ const navConfig = siteSettingsData?.navConfig;
9
+ const visibleNavItems = filterNavItems(navItems, navConfig, permissions);
10
+ return _jsx(MainNavbar, { navItems: visibleNavItems, hiddenNavItems: hiddenNavItems });
11
+ }
@@ -0,0 +1,8 @@
1
+ import type { FacetOption } from "../../filters/FilterFacetSection";
2
+ import type { UrlTable } from "../../filters/FilterPanel";
3
+ export interface LiveItemFiltersProps {
4
+ table: UrlTable;
5
+ categoryOptions?: FacetOption[];
6
+ currencyPrefix?: string;
7
+ }
8
+ export declare function LiveItemFilters({ table, categoryOptions, currencyPrefix, }: LiveItemFiltersProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,23 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { FilterFacetSection } from "../../filters/FilterFacetSection";
4
+ import { RangeFilter } from "../../filters/RangeFilter";
5
+ import { Div } from "../../../ui";
6
+ const SEX_OPTIONS = [
7
+ { value: "male", label: "Male" },
8
+ { value: "female", label: "Female" },
9
+ { value: "unknown", label: "Unknown" },
10
+ ];
11
+ const TRANSPORT_OPTIONS = [
12
+ { value: "in-person", label: "In-Person only" },
13
+ { value: "courier", label: "Live-animal courier" },
14
+ { value: "specialist", label: "Specialist transport" },
15
+ ];
16
+ export function LiveItemFilters({ table, categoryOptions = [], currencyPrefix = "₹", }) {
17
+ const selectedCategories = table.get("category")
18
+ ? table.get("category").split("|").filter(Boolean)
19
+ : [];
20
+ const selectedSex = table.get("liveSex") ? [table.get("liveSex")] : [];
21
+ const selectedTransport = table.get("liveTransportMethod") ? [table.get("liveTransportMethod")] : [];
22
+ return (_jsxs(Div, { children: [categoryOptions.length > 0 && (_jsx(FilterFacetSection, { title: "Category", options: categoryOptions, selected: selectedCategories, onChange: (vals) => table.set("category", vals.join("|")), searchable: true, defaultCollapsed: categoryOptions.length > 6 })), _jsxs("div", { className: "border-t border-[var(--appkit-color-border)] pt-4 mt-4", children: [_jsx("label", { className: "block text-sm font-medium text-[var(--appkit-color-text)] mb-2", children: "Species / Animal" }), _jsx("input", { type: "text", value: table.get("species") || "", onChange: (e) => table.set("species", e.target.value), placeholder: "e.g. Axolotl, Parrot", className: "w-full rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-3 py-2 text-sm text-[var(--appkit-color-text)] placeholder-[var(--appkit-color-text-faint)] focus:outline-none focus:ring-2 focus:ring-[var(--appkit-color-primary)]" })] }), _jsxs("div", { className: "border-t border-[var(--appkit-color-border)] pt-4 mt-4", children: [_jsx("label", { className: "block text-sm font-medium text-[var(--appkit-color-text)] mb-2", children: "Jurisdiction (state/UT)" }), _jsx("input", { type: "text", value: table.get("jurisdiction") || "", onChange: (e) => table.set("jurisdiction", e.target.value), placeholder: "e.g. Maharashtra", className: "w-full rounded-lg border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-3 py-2 text-sm text-[var(--appkit-color-text)] placeholder-[var(--appkit-color-text-faint)] focus:outline-none focus:ring-2 focus:ring-[var(--appkit-color-primary)]" })] }), _jsx(FilterFacetSection, { title: "Sex", options: SEX_OPTIONS, selected: selectedSex, onChange: (vals) => table.set("liveSex", vals[0] ?? ""), searchable: false, selectionMode: "single", defaultCollapsed: false }), _jsx(FilterFacetSection, { title: "Transport Method", options: TRANSPORT_OPTIONS, selected: selectedTransport, onChange: (vals) => table.set("liveTransportMethod", vals[0] ?? ""), searchable: false, selectionMode: "single", defaultCollapsed: false }), _jsx(RangeFilter, { title: "Price", minValue: table.get("minPrice"), maxValue: table.get("maxPrice"), onMinChange: (v) => table.set("minPrice", v), onMaxChange: (v) => table.set("maxPrice", v), prefix: currencyPrefix, showSlider: true, minBound: 0, maxBound: 200000, step: 100, minPlaceholder: "Min price", maxPlaceholder: "Max price", defaultCollapsed: false })] }));
23
+ }
@@ -0,0 +1,4 @@
1
+ export interface LiveItemsIndexListingProps {
2
+ initialData?: any;
3
+ }
4
+ export declare function LiveItemsIndexListing({ initialData }: LiveItemsIndexListingProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,108 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState, useCallback } from "react";
4
+ import { useUrlTable } from "../../../react/hooks/useUrlTable";
5
+ import { useProducts } from "../../products/hooks/useProducts";
6
+ import { BulkActionBar, FilterDrawer, ListingToolbar, LoginRequiredModal, Pagination, Text, useToast } from "../../../ui";
7
+ import { usePendingTable } from "../../../react/hooks/usePendingTable";
8
+ import { useAuthGate } from "../../../react/hooks/useAuthGate";
9
+ import { useBulkSelection } from "../../../react/hooks/useBulkSelection";
10
+ import { useGuestWishlist } from "../../wishlist/hooks/useGuestWishlist";
11
+ import { pushWishlistOp } from "../../cart/utils/pending-ops";
12
+ import { useCategoryTree, categoriesToFacetOptions } from "../../categories/hooks/useCategoryTree";
13
+ import { TABLE_KEYS, VIEW_MODE } from "../../../constants/table-keys";
14
+ import { sortBy } from "../../../constants/sort";
15
+ import { PRODUCT_FIELDS } from "../../../constants/field-names";
16
+ import { ROUTES } from "../../../next";
17
+ import { InteractiveProductCard } from "../../products/components/InteractiveProductCard";
18
+ import { LiveItemFilters } from "./LiveItemFilters";
19
+ import { ACTION_ID } from "../../products/constants/action-defs";
20
+ const DEFAULT_SORT = sortBy(PRODUCT_FIELDS.CREATED_AT);
21
+ const SORT_OPTIONS = [
22
+ { value: sortBy(PRODUCT_FIELDS.CREATED_AT), label: "Newest First" },
23
+ { value: sortBy(PRODUCT_FIELDS.CREATED_AT, "ASC"), label: "Oldest First" },
24
+ { value: sortBy(PRODUCT_FIELDS.PRICE, "ASC"), label: "Price: Low to High" },
25
+ { value: sortBy(PRODUCT_FIELDS.PRICE), label: "Price: High to Low" },
26
+ ];
27
+ const FILTER_KEYS = [
28
+ TABLE_KEYS.CATEGORY,
29
+ TABLE_KEYS.SPECIES,
30
+ TABLE_KEYS.JURISDICTION,
31
+ TABLE_KEYS.MIN_PRICE,
32
+ TABLE_KEYS.MAX_PRICE,
33
+ ];
34
+ export function LiveItemsIndexListing({ initialData }) {
35
+ const table = useUrlTable({ defaults: { pageSize: "24", sort: DEFAULT_SORT } });
36
+ const { showToast } = useToast();
37
+ const { requireAuth, modalOpen, modalMessage, closeModal } = useAuthGate();
38
+ const [searchInput, setSearchInput] = useState(table.get(TABLE_KEYS.QUERY) || "");
39
+ const [filterOpen, setFilterOpen] = useState(false);
40
+ const [view, setView] = useState(table.get(TABLE_KEYS.VIEW) || VIEW_MODE.GRID);
41
+ const localWishlist = useGuestWishlist();
42
+ const { categories } = useCategoryTree();
43
+ const categoryOptions = categoriesToFacetOptions(categories);
44
+ const wishlistedIds = new Set(localWishlist.items.filter((i) => i.type === "live").map((i) => i.itemId));
45
+ const { pendingTable, filterActiveCount, onFilterApply, onFilterClear, onFilterReset } = usePendingTable(table, FILTER_KEYS);
46
+ const openFilters = useCallback(() => {
47
+ onFilterReset();
48
+ setFilterOpen(true);
49
+ }, [onFilterReset]);
50
+ const applyFilters = useCallback(() => {
51
+ onFilterApply();
52
+ setFilterOpen(false);
53
+ }, [onFilterApply]);
54
+ const resetAll = useCallback(() => {
55
+ table.setMany({ [TABLE_KEYS.QUERY]: "", [TABLE_KEYS.SORT]: "" });
56
+ onFilterClear();
57
+ setSearchInput("");
58
+ }, [table, onFilterClear]);
59
+ const hasActiveState = !!table.get(TABLE_KEYS.QUERY) ||
60
+ table.get(TABLE_KEYS.SORT) !== DEFAULT_SORT ||
61
+ filterActiveCount > 0;
62
+ const params = {
63
+ q: table.get(TABLE_KEYS.QUERY) || undefined,
64
+ category: table.get(TABLE_KEYS.CATEGORY) || undefined,
65
+ minPrice: table.get(TABLE_KEYS.MIN_PRICE) ? Number(table.get(TABLE_KEYS.MIN_PRICE)) : undefined,
66
+ maxPrice: table.get(TABLE_KEYS.MAX_PRICE) ? Number(table.get(TABLE_KEYS.MAX_PRICE)) : undefined,
67
+ sort: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT,
68
+ page: table.getNumber(TABLE_KEYS.PAGE, 1),
69
+ perPage: table.getNumber(TABLE_KEYS.PAGE_SIZE, 24),
70
+ listingType: "live",
71
+ };
72
+ const { products, totalPages, page, isLoading } = useProducts(params, { initialData });
73
+ const commitSearch = useCallback(() => {
74
+ table.set(TABLE_KEYS.QUERY, searchInput.trim());
75
+ }, [searchInput, table]);
76
+ const selection = useBulkSelection({ items: products, keyExtractor: (p) => p.id });
77
+ const gridClass = "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4";
78
+ const wishlistActions = {
79
+ addToWishlist: (productId) => {
80
+ requireAuth(ACTION_ID.ADD_TO_WISHLIST, () => {
81
+ localWishlist.add(productId, "live");
82
+ pushWishlistOp({ op: "add", itemId: productId, type: "live" });
83
+ showToast("Added to wishlist", "success");
84
+ });
85
+ return Promise.resolve();
86
+ },
87
+ removeFromWishlist: (productId) => {
88
+ requireAuth(ACTION_ID.REMOVE_FROM_WISHLIST, () => {
89
+ localWishlist.remove(productId, "live");
90
+ pushWishlistOp({ op: "remove", itemId: productId, type: "live" });
91
+ showToast("Removed from wishlist", "info");
92
+ });
93
+ return Promise.resolve();
94
+ },
95
+ isWishlisted: (productId) => wishlistedIds.has(productId),
96
+ };
97
+ function handleToggleWishlist(id) {
98
+ if (wishlistActions.isWishlisted(id)) {
99
+ wishlistActions.removeFromWishlist(id);
100
+ }
101
+ else {
102
+ wishlistActions.addToWishlist(id);
103
+ }
104
+ }
105
+ return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: filterActiveCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search live items\u2026", onSearchChange: setSearchInput, onSearchCommit: commitSearch, onSearchKeyDown: (e) => { if (e.key === "Enter")
106
+ commitSearch(); }, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, view: view, onViewChange: (v) => { if (v !== "table")
107
+ setView(v); }, onResetAll: resetAll, hasActiveState: hasActiveState, bulkMode: selection.isSelecting, bulkSelectedCount: selection.selectedCount, bulkTotalCount: products.length, onBulkSelectAll: selection.toggleAll, onBulkClear: selection.clearSelection }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [] }), totalPages > 1 && (_jsx("div", { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 flex justify-center bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-b border-zinc-200 dark:border-slate-700 px-3 py-1.5", children: _jsx(Pagination, { currentPage: page, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), _jsx("div", { className: "py-6", children: isLoading ? (_jsx("div", { className: gridClass, children: Array.from({ length: 10 }).map((_, i) => (_jsxs("div", { className: "rounded-xl border border-zinc-100 dark:border-slate-700 overflow-hidden animate-pulse", children: [_jsx("div", { className: "aspect-square bg-zinc-200 dark:bg-slate-700" }), _jsxs("div", { className: "p-3 space-y-2", children: [_jsx("div", { className: "h-3 bg-zinc-200 dark:bg-slate-700 rounded w-3/4" }), _jsx("div", { className: "h-4 bg-zinc-200 dark:bg-slate-700 rounded w-1/3" })] })] }, i))) })) : products.length === 0 ? (_jsx(Text, { className: "py-12 text-center text-sm text-zinc-500 dark:text-zinc-400", children: "No live item listings found." })) : (_jsx("div", { className: view === "list" ? "flex flex-col divide-y divide-zinc-100 dark:divide-zinc-800 rounded-xl border border-zinc-100 dark:border-zinc-800" : gridClass, children: products.map((product) => (_jsx(InteractiveProductCard, { product: product, href: String(ROUTES.PUBLIC.LIVE_DETAIL(product.id)), variant: view === "list" ? "list" : "grid", isWishlisted: wishlistActions.isWishlisted(product.id), onToggleWishlist: handleToggleWishlist, selectable: selection.isSelecting, isSelected: selection.isSelected(product.id), onSelect: (id) => selection.toggle(id) }, product.id))) })) }), _jsx(FilterDrawer, { open: filterOpen, onOpen: openFilters, onClose: () => setFilterOpen(false), onApply: applyFilters, onReset: onFilterClear, activeCount: filterActiveCount, hideTrigger: true, children: _jsx(LiveItemFilters, { table: pendingTable, categoryOptions: categoryOptions }) }), _jsx(LoginRequiredModal, { isOpen: modalOpen, onClose: closeModal, message: modalMessage })] }));
108
+ }
@@ -0,0 +1,6 @@
1
+ type SearchParams = Record<string, string | string[]>;
2
+ export interface LiveItemsListViewProps {
3
+ searchParams?: SearchParams;
4
+ }
5
+ export declare function LiveItemsListView({ searchParams }: LiveItemsListViewProps): Promise<import("react/jsx-runtime").JSX.Element>;
6
+ export {};
@@ -0,0 +1,43 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { productRepository } from "../../../repositories";
3
+ import { Container, Heading, Main, Section } from "../../../ui";
4
+ import { AdSlot } from "../../homepage/components/AdSlot";
5
+ import { parseListingSearchParams } from "../../../utils/listing-params";
6
+ import { LiveItemsIndexListing } from "./LiveItemsIndexListing";
7
+ const DEFAULT_PAGE = 1;
8
+ const DEFAULT_PAGE_SIZE = 24;
9
+ const DEFAULT_SORT = "-createdAt";
10
+ function sp(params, key) {
11
+ const v = params[key];
12
+ return Array.isArray(v) ? v[0] ?? "" : v ?? "";
13
+ }
14
+ function buildLiveFilters(params) {
15
+ const parts = ["status==published", "listingType==live"];
16
+ const minPrice = sp(params, "minPrice");
17
+ const maxPrice = sp(params, "maxPrice");
18
+ if (minPrice)
19
+ parts.push(`price>=${minPrice}`);
20
+ if (maxPrice)
21
+ parts.push(`price<=${maxPrice}`);
22
+ const species = sp(params, "species");
23
+ if (species)
24
+ parts.push(`liveSpecies==${species}`);
25
+ const liveSex = sp(params, "liveSex");
26
+ if (liveSex)
27
+ parts.push(`liveSex==${liveSex}`);
28
+ const transport = sp(params, "liveTransportMethod");
29
+ if (transport)
30
+ parts.push(`liveTransportMethod==${transport}`);
31
+ return parts.join(",");
32
+ }
33
+ export async function LiveItemsListView({ searchParams = {} }) {
34
+ const std = parseListingSearchParams(searchParams);
35
+ const sort = std.sorts ?? DEFAULT_SORT;
36
+ const page = std.page ?? DEFAULT_PAGE;
37
+ const pageSize = std.pageSize ?? DEFAULT_PAGE_SIZE;
38
+ const filters = buildLiveFilters(searchParams);
39
+ const result = await productRepository
40
+ .list({ filters, sorts: sort, page, pageSize })
41
+ .catch(() => null);
42
+ return (_jsx(Main, { children: _jsx(Section, { className: "py-10", children: _jsxs(Container, { size: "xl", children: [_jsx(Heading, { level: 1, className: "mb-8 text-3xl font-semibold text-zinc-900", children: "Live Items" }), _jsx(AdSlot, { id: "listing-sidebar-top", className: "mb-6" }), _jsx(LiveItemsIndexListing, { initialData: result ?? undefined }), _jsx(AdSlot, { id: "listing-sidebar-bottom", className: "mt-8" })] }) }) }));
43
+ }
@@ -0,0 +1,6 @@
1
+ export { LiveItemsListView } from "./LiveItemsListView";
2
+ export type { LiveItemsListViewProps } from "./LiveItemsListView";
3
+ export { LiveItemsIndexListing } from "./LiveItemsIndexListing";
4
+ export type { LiveItemsIndexListingProps } from "./LiveItemsIndexListing";
5
+ export { LiveItemFilters } from "./LiveItemFilters";
6
+ export type { LiveItemFiltersProps } from "./LiveItemFilters";
@@ -0,0 +1,3 @@
1
+ export { LiveItemsListView } from "./LiveItemsListView";
2
+ export { LiveItemsIndexListing } from "./LiveItemsIndexListing";
3
+ export { LiveItemFilters } from "./LiveItemFilters";