@mohasinac/appkit 2.7.59 → 2.8.1

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 (324) hide show
  1. package/dist/_internal/client/features/filters/filter-load-options.d.ts +4 -5
  2. package/dist/_internal/server/features/auctions/og.js +8 -32
  3. package/dist/_internal/server/features/blog/og.js +10 -49
  4. package/dist/_internal/server/features/checkout/actions.js +6 -0
  5. package/dist/_internal/server/features/classified/og.js +9 -51
  6. package/dist/_internal/server/features/digital-code/actions.d.ts +11 -0
  7. package/dist/_internal/server/features/digital-code/actions.js +30 -0
  8. package/dist/_internal/server/features/digital-code/index.d.ts +1 -0
  9. package/dist/_internal/server/features/digital-code/index.js +1 -0
  10. package/dist/_internal/server/features/digital-code/og.js +9 -51
  11. package/dist/_internal/server/features/events/og.js +10 -49
  12. package/dist/_internal/server/features/item-requests/data.d.ts +17 -0
  13. package/dist/_internal/server/features/item-requests/data.js +20 -0
  14. package/dist/_internal/server/features/item-requests/index.d.ts +2 -0
  15. package/dist/_internal/server/features/item-requests/index.js +2 -0
  16. package/dist/_internal/server/features/item-requests/og.d.ts +40 -0
  17. package/dist/_internal/server/features/item-requests/og.js +136 -0
  18. package/dist/_internal/server/features/live/actions.d.ts +5 -0
  19. package/dist/_internal/server/features/live/actions.js +24 -0
  20. package/dist/_internal/server/features/live/index.d.ts +1 -0
  21. package/dist/_internal/server/features/live/index.js +1 -0
  22. package/dist/_internal/server/features/live/og.js +9 -51
  23. package/dist/_internal/server/features/media/contextGuards.js +19 -8
  24. package/dist/_internal/server/features/pre-orders/og.js +8 -32
  25. package/dist/_internal/server/features/prize-draws/data.d.ts +17 -0
  26. package/dist/_internal/server/features/prize-draws/data.js +20 -0
  27. package/dist/_internal/server/features/prize-draws/index.d.ts +2 -0
  28. package/dist/_internal/server/features/prize-draws/index.js +2 -0
  29. package/dist/_internal/server/features/prize-draws/og.d.ts +30 -0
  30. package/dist/_internal/server/features/prize-draws/og.js +50 -0
  31. package/dist/_internal/server/features/products/og.js +8 -33
  32. package/dist/_internal/server/features/seo/og-layout.d.ts +42 -0
  33. package/dist/_internal/server/features/seo/og-layout.js +69 -0
  34. package/dist/_internal/server/features/stores/og.js +8 -41
  35. package/dist/_internal/server/features/sublisting-categories/og.js +11 -42
  36. package/dist/client.d.ts +10 -6
  37. package/dist/client.js +7 -3
  38. package/dist/constants/index.d.ts +4 -0
  39. package/dist/constants/index.js +2 -0
  40. package/dist/constants/notification-types.d.ts +20 -0
  41. package/dist/constants/notification-types.js +37 -0
  42. package/dist/constants/pagination-presets.d.ts +39 -0
  43. package/dist/constants/pagination-presets.js +38 -0
  44. package/dist/errors/messages.d.ts +0 -4
  45. package/dist/errors/messages.js +0 -4
  46. package/dist/features/about/components/PublicProfileView.js +8 -8
  47. package/dist/features/account/components/UserOffersPanel.js +1 -1
  48. package/dist/features/account/components/UserSupportView.d.ts +1 -2
  49. package/dist/features/account/components/UserSupportView.js +9 -1
  50. package/dist/features/admin/actions/admin-actions.js +16 -1
  51. package/dist/features/admin/components/AdminAllEventEntriesView.d.ts +2 -3
  52. package/dist/features/admin/components/AdminAllEventEntriesView.js +50 -83
  53. package/dist/features/admin/components/AdminBidsView.d.ts +2 -3
  54. package/dist/features/admin/components/AdminBidsView.js +64 -98
  55. package/dist/features/admin/components/AdminBlogView.d.ts +3 -7
  56. package/dist/features/admin/components/AdminBlogView.js +53 -83
  57. package/dist/features/admin/components/AdminBrandsView.d.ts +2 -3
  58. package/dist/features/admin/components/AdminBrandsView.js +84 -83
  59. package/dist/features/admin/components/AdminBundlesView.js +82 -125
  60. package/dist/features/admin/components/AdminCarouselView.d.ts +2 -2
  61. package/dist/features/admin/components/AdminCarouselView.js +17 -52
  62. package/dist/features/admin/components/AdminCartsView.d.ts +2 -3
  63. package/dist/features/admin/components/AdminCartsView.js +39 -88
  64. package/dist/features/admin/components/AdminCategoriesView.d.ts +3 -3
  65. package/dist/features/admin/components/AdminCategoriesView.js +98 -92
  66. package/dist/features/admin/components/AdminCategoryEditorView.js +2 -2
  67. package/dist/features/admin/components/AdminClassifiedView.d.ts +3 -0
  68. package/dist/features/admin/components/AdminClassifiedView.js +44 -0
  69. package/dist/features/admin/components/AdminContactView.d.ts +2 -2
  70. package/dist/features/admin/components/AdminContactView.js +104 -111
  71. package/dist/features/admin/components/AdminCouponsView.d.ts +3 -6
  72. package/dist/features/admin/components/AdminCouponsView.js +66 -86
  73. package/dist/features/admin/components/AdminDigitalCodesView.d.ts +3 -0
  74. package/dist/features/admin/components/AdminDigitalCodesView.js +51 -0
  75. package/dist/features/admin/components/AdminFaqsView.d.ts +4 -4
  76. package/dist/features/admin/components/AdminFaqsView.js +77 -33
  77. package/dist/features/admin/components/AdminFeaturesView.d.ts +2 -3
  78. package/dist/features/admin/components/AdminFeaturesView.js +57 -70
  79. package/dist/features/admin/components/AdminGroupedListingsView.d.ts +3 -0
  80. package/dist/features/admin/components/AdminGroupedListingsView.js +43 -0
  81. package/dist/features/admin/components/AdminHistoryView.d.ts +2 -3
  82. package/dist/features/admin/components/AdminHistoryView.js +35 -52
  83. package/dist/features/admin/components/AdminListingScaffold.d.ts +2 -2
  84. package/dist/features/admin/components/AdminListingScaffold.js +3 -3
  85. package/dist/features/admin/components/AdminLiveView.d.ts +3 -0
  86. package/dist/features/admin/components/AdminLiveView.js +50 -0
  87. package/dist/features/admin/components/AdminNewsletterView.d.ts +2 -2
  88. package/dist/features/admin/components/AdminNewsletterView.js +67 -97
  89. package/dist/features/admin/components/AdminNotificationsView.d.ts +2 -3
  90. package/dist/features/admin/components/AdminNotificationsView.js +67 -93
  91. package/dist/features/admin/components/AdminOrderEditorView.js +10 -10
  92. package/dist/features/admin/components/AdminOrdersView.d.ts +2 -3
  93. package/dist/features/admin/components/AdminOrdersView.js +93 -107
  94. package/dist/features/admin/components/AdminPayoutsView.d.ts +2 -3
  95. package/dist/features/admin/components/AdminPayoutsView.js +51 -91
  96. package/dist/features/admin/components/AdminPrizeDrawsView.d.ts +2 -3
  97. package/dist/features/admin/components/AdminPrizeDrawsView.js +39 -76
  98. package/dist/features/admin/components/AdminProductEditorView.js +3 -3
  99. package/dist/features/admin/components/AdminProductsView.d.ts +4 -4
  100. package/dist/features/admin/components/AdminProductsView.js +167 -163
  101. package/dist/features/admin/components/AdminReturnRequestsView.d.ts +1 -1
  102. package/dist/features/admin/components/AdminReturnRequestsView.js +64 -66
  103. package/dist/features/admin/components/AdminReviewsView.d.ts +3 -7
  104. package/dist/features/admin/components/AdminReviewsView.js +94 -110
  105. package/dist/features/admin/components/AdminScammersView.d.ts +2 -3
  106. package/dist/features/admin/components/AdminScammersView.js +53 -97
  107. package/dist/features/admin/components/AdminSectionsView.js +1 -1
  108. package/dist/features/admin/components/AdminSessionsView.d.ts +2 -3
  109. package/dist/features/admin/components/AdminSessionsView.js +62 -89
  110. package/dist/features/admin/components/AdminSiteSettingsView.js +4 -5
  111. package/dist/features/admin/components/AdminStoreAddressesView.d.ts +1 -1
  112. package/dist/features/admin/components/AdminStoreAddressesView.js +39 -53
  113. package/dist/features/admin/components/AdminStoreEditorView.js +21 -8
  114. package/dist/features/admin/components/AdminStoresView.d.ts +2 -3
  115. package/dist/features/admin/components/AdminStoresView.js +67 -99
  116. package/dist/features/admin/components/AdminSublistingCategoriesView.d.ts +1 -1
  117. package/dist/features/admin/components/AdminSublistingCategoriesView.js +28 -44
  118. package/dist/features/admin/components/AdminSupportTicketDetailView.d.ts +10 -1
  119. package/dist/features/admin/components/AdminSupportTicketDetailView.js +191 -5
  120. package/dist/features/admin/components/AdminSupportTicketsView.d.ts +2 -3
  121. package/dist/features/admin/components/AdminSupportTicketsView.js +65 -96
  122. package/dist/features/admin/components/AdminTeamView.d.ts +2 -2
  123. package/dist/features/admin/components/AdminTeamView.js +40 -74
  124. package/dist/features/admin/components/AdminUserEditorView.d.ts +11 -1
  125. package/dist/features/admin/components/AdminUserEditorView.js +77 -7
  126. package/dist/features/admin/components/AdminUsersView.d.ts +2 -3
  127. package/dist/features/admin/components/AdminUsersView.js +108 -100
  128. package/dist/features/admin/components/AdminViewCards.d.ts +1 -1
  129. package/dist/features/admin/components/AdminViewCards.js +15 -15
  130. package/dist/features/admin/components/AdminWishlistsView.d.ts +2 -3
  131. package/dist/features/admin/components/AdminWishlistsView.js +36 -62
  132. package/dist/features/admin/components/DataListingView.d.ts +122 -0
  133. package/dist/features/admin/components/DataListingView.js +66 -0
  134. package/dist/features/admin/components/index.d.ts +10 -4
  135. package/dist/features/admin/components/index.js +6 -2
  136. package/dist/features/admin/constants/filter-tabs.d.ts +23 -17
  137. package/dist/features/admin/constants/filter-tabs.js +21 -17
  138. package/dist/features/admin/hooks/useAdminListing.d.ts +1 -0
  139. package/dist/features/admin/hooks/useAdminListing.js +1 -1
  140. package/dist/features/admin/schemas/firestore.js +6 -7
  141. package/dist/features/auctions/server.d.ts +0 -1
  142. package/dist/features/auctions/server.js +0 -1
  143. package/dist/features/auth/actions/realtime-token-actions.js +1 -1
  144. package/dist/features/auth/repository/user.repository.js +1 -1
  145. package/dist/features/blog/components/BlogFeaturedCard.js +1 -0
  146. package/dist/features/cart/repository/cart.repository.d.ts +4 -1
  147. package/dist/features/cart/repository/cart.repository.js +12 -0
  148. package/dist/features/checkout/hooks/useCheckoutApi.d.ts +0 -2
  149. package/dist/features/checkout/index.d.ts +1 -1
  150. package/dist/features/events/components/AdminEventEditorView.js +10 -13
  151. package/dist/features/events/components/AdminEventsView.d.ts +3 -3
  152. package/dist/features/events/components/AdminEventsView.js +50 -86
  153. package/dist/features/events/components/EventCard.js +1 -0
  154. package/dist/features/events/components/EventOfferCard.d.ts +19 -0
  155. package/dist/features/events/components/EventOfferCard.js +29 -0
  156. package/dist/features/events/components/EventRaffleEntryForm.d.ts +25 -0
  157. package/dist/features/events/components/EventRaffleEntryForm.js +37 -0
  158. package/dist/features/events/components/EventRafflesSection.d.ts +1 -4
  159. package/dist/features/events/components/EventRafflesSection.js +17 -6
  160. package/dist/features/events/components/EventSaleBanner.d.ts +21 -0
  161. package/dist/features/events/components/EventSaleBanner.js +18 -0
  162. package/dist/features/events/components/index.d.ts +6 -0
  163. package/dist/features/events/components/index.js +4 -0
  164. package/dist/features/events/repository/event-entry.repository.d.ts +5 -0
  165. package/dist/features/events/repository/event-entry.repository.js +7 -0
  166. package/dist/features/faq/components/FAQPageContent.js +1 -0
  167. package/dist/features/filters/AsyncFacetSection.d.ts +1 -1
  168. package/dist/features/homepage/components/AdvertisementBanner.js +6 -6
  169. package/dist/features/homepage/components/FAQSection.d.ts +0 -5
  170. package/dist/features/homepage/components/HomepageSkeleton.js +2 -2
  171. package/dist/features/homepage/components/WelcomeSection.js +3 -3
  172. package/dist/features/homepage/lib/live-stats.js +1 -1
  173. package/dist/features/homepage/schemas/firestore.d.ts +0 -2
  174. package/dist/features/layout/TitleBar.js +1 -0
  175. package/dist/features/layout/index.d.ts +0 -2
  176. package/dist/features/layout/index.js +0 -1
  177. package/dist/features/pre-orders/server.d.ts +0 -1
  178. package/dist/features/pre-orders/server.js +0 -1
  179. package/dist/features/products/components/GroupSettingsPanel.js +2 -2
  180. package/dist/features/products/components/PrizeDrawItemsEditor.js +2 -2
  181. package/dist/features/products/components/PrizeDrawsSection.d.ts +1 -4
  182. package/dist/features/products/components/PrizeDrawsSection.js +17 -6
  183. package/dist/features/products/components/PrizeRevealModal.js +1 -1
  184. package/dist/features/products/components/ProductCardMetadataSection.d.ts +11 -0
  185. package/dist/features/products/components/ProductCardMetadataSection.js +25 -0
  186. package/dist/features/products/components/ProductDetailPageView.js +3 -1
  187. package/dist/features/products/components/ProductFeaturesSelector.js +1 -1
  188. package/dist/features/products/components/ProductGradingTab.d.ts +13 -0
  189. package/dist/features/products/components/ProductGradingTab.js +25 -0
  190. package/dist/features/products/components/ProductGrid.js +15 -2
  191. package/dist/features/products/components/ProductTabsShell.d.ts +5 -1
  192. package/dist/features/products/components/ProductTabsShell.js +6 -1
  193. package/dist/features/products/components/index.d.ts +4 -0
  194. package/dist/features/products/components/index.js +3 -0
  195. package/dist/features/products/constants/action-defs.d.ts +5 -0
  196. package/dist/features/products/constants/action-defs.js +52 -32
  197. package/dist/features/products/constants/sieve.d.ts +24 -4
  198. package/dist/features/products/constants/sieve.js +20 -11
  199. package/dist/features/products/schemas/firestore.d.ts +17 -0
  200. package/dist/features/products/schemas/product-features.validators.d.ts +2 -2
  201. package/dist/features/products/schemas/product-templates.d.ts +2 -4
  202. package/dist/features/products/types/index.d.ts +4 -0
  203. package/dist/features/promotions/components/CouponsIndexListing.js +4 -4
  204. package/dist/features/promotions/server.d.ts +0 -1
  205. package/dist/features/promotions/server.js +0 -1
  206. package/dist/features/reviews/components/ReviewDetailShell.js +3 -3
  207. package/dist/features/search/api/route.js +44 -1
  208. package/dist/features/search/components/Search.js +2 -0
  209. package/dist/features/search/hooks/useNavSuggestions.d.ts +5 -1
  210. package/dist/features/search/hooks/useNavSuggestions.js +31 -4
  211. package/dist/features/seller/components/BrandInlineSelect.js +2 -2
  212. package/dist/features/seller/components/CategoryInlineSelect.js +2 -2
  213. package/dist/features/seller/components/SellerAddressesView.js +4 -5
  214. package/dist/features/seller/components/SellerAuctionsView.d.ts +3 -3
  215. package/dist/features/seller/components/SellerAuctionsView.js +60 -90
  216. package/dist/features/seller/components/SellerBidsView.js +1 -1
  217. package/dist/features/seller/components/SellerBundlesView.js +64 -89
  218. package/dist/features/seller/components/SellerClassifiedView.js +67 -90
  219. package/dist/features/seller/components/SellerCouponEditorView.js +1 -1
  220. package/dist/features/seller/components/SellerCouponsView.d.ts +2 -2
  221. package/dist/features/seller/components/SellerCouponsView.js +45 -84
  222. package/dist/features/seller/components/SellerDigitalCodesView.js +63 -88
  223. package/dist/features/seller/components/SellerGroupedListingsView.js +33 -49
  224. package/dist/features/seller/components/SellerLiveView.js +63 -84
  225. package/dist/features/seller/components/SellerOffersPanel.js +1 -1
  226. package/dist/features/seller/components/SellerOffersView.d.ts +2 -2
  227. package/dist/features/seller/components/SellerOffersView.js +37 -69
  228. package/dist/features/seller/components/SellerOrdersView.d.ts +2 -2
  229. package/dist/features/seller/components/SellerOrdersView.js +4 -4
  230. package/dist/features/seller/components/SellerPayoutMethodsView.js +1 -1
  231. package/dist/features/seller/components/SellerPayoutsView.d.ts +2 -2
  232. package/dist/features/seller/components/SellerPayoutsView.js +34 -68
  233. package/dist/features/seller/components/SellerPreOrdersView.d.ts +2 -2
  234. package/dist/features/seller/components/SellerPreOrdersView.js +49 -82
  235. package/dist/features/seller/components/SellerPrizeDrawsView.d.ts +2 -2
  236. package/dist/features/seller/components/SellerPrizeDrawsView.js +49 -82
  237. package/dist/features/seller/components/SellerProductShell.d.ts +1 -1
  238. package/dist/features/seller/components/SellerProductsView.d.ts +2 -2
  239. package/dist/features/seller/components/SellerProductsView.js +15 -10
  240. package/dist/features/seller/components/SellerShippingConfigsView.js +1 -1
  241. package/dist/features/seller/components/SellerSidebar.d.ts +0 -4
  242. package/dist/features/seller/components/SellerSidebar.js +0 -2
  243. package/dist/features/seller/components/SellerStoreCategoriesView.js +1 -1
  244. package/dist/features/seller/components/SellerTemplatesView.js +2 -2
  245. package/dist/features/seller/components/SellersListView.d.ts +1 -2
  246. package/dist/features/seller/components/analytics/SellerAnalyticsStats.d.ts +5 -0
  247. package/dist/features/seller/components/analytics/SellerAnalyticsStats.js +2 -8
  248. package/dist/features/seller/components/index.d.ts +0 -3
  249. package/dist/features/seller/components/index.js +0 -2
  250. package/dist/features/seller/server.d.ts +0 -1
  251. package/dist/features/seller/server.js +0 -1
  252. package/dist/features/shell/FormShell.d.ts +1 -1
  253. package/dist/features/shell/FormShell.js +7 -4
  254. package/dist/features/shell/field-groups/ImageFieldGroup.d.ts +18 -0
  255. package/dist/features/shell/field-groups/ImageFieldGroup.js +15 -0
  256. package/dist/features/shell/field-groups/SeoFieldGroup.d.ts +22 -0
  257. package/dist/features/shell/field-groups/SeoFieldGroup.js +16 -0
  258. package/dist/features/shell/field-groups/StatusFieldGroup.d.ts +35 -0
  259. package/dist/features/shell/field-groups/StatusFieldGroup.js +16 -0
  260. package/dist/features/shell/field-groups/TitleDescriptionGroup.d.ts +40 -0
  261. package/dist/features/shell/field-groups/TitleDescriptionGroup.js +16 -0
  262. package/dist/features/shell/field-groups/index.d.ts +13 -0
  263. package/dist/features/shell/field-groups/index.js +9 -0
  264. package/dist/features/shell/index.d.ts +2 -0
  265. package/dist/features/shell/index.js +1 -0
  266. package/dist/features/stores/components/StoreCapabilitiesGuideView.d.ts +1 -2
  267. package/dist/features/stores/components/StoreFinanceGuideView.d.ts +1 -2
  268. package/dist/features/stores/components/StoreHeader.js +2 -1
  269. package/dist/features/stores/components/StoreListingsGuideView.d.ts +1 -2
  270. package/dist/features/stores/components/StoreOrdersGuideView.d.ts +1 -2
  271. package/dist/features/stores/components/StoreScopedSearch.d.ts +16 -0
  272. package/dist/features/stores/components/StoreScopedSearch.js +27 -0
  273. package/dist/features/stores/components/StoreSettingsGuideView.d.ts +1 -2
  274. package/dist/features/stores/server.d.ts +0 -1
  275. package/dist/features/stores/server.js +0 -1
  276. package/dist/features/support/schemas/firestore.d.ts +22 -1
  277. package/dist/features/support/schemas/firestore.js +10 -0
  278. package/dist/features/wishlist/server.d.ts +0 -1
  279. package/dist/features/wishlist/server.js +0 -1
  280. package/dist/index.d.ts +9 -27
  281. package/dist/index.js +14 -50
  282. package/dist/next/routing/route-map.d.ts +8 -0
  283. package/dist/next/routing/route-map.js +4 -0
  284. package/dist/react/hooks/useListingTypeFlags.d.ts +32 -0
  285. package/dist/react/hooks/useListingTypeFlags.js +19 -0
  286. package/dist/security/index.d.ts +1 -1
  287. package/dist/security/index.js +1 -1
  288. package/dist/security/pii-redact.d.ts +8 -0
  289. package/dist/security/pii-redact.js +10 -1
  290. package/dist/seed/grouped-listings-seed-data.d.ts +4 -0
  291. package/dist/seed/products-preorders-seed-data.d.ts +4 -0
  292. package/dist/seed/products-prize-draws-seed-data.js +3 -0
  293. package/dist/seed/site-settings-seed-data.js +5 -5
  294. package/dist/seed/sub-listings-seed-data.d.ts +4 -0
  295. package/dist/server.d.ts +2 -0
  296. package/dist/server.js +4 -0
  297. package/dist/styles.css +54 -395
  298. package/dist/tailwind-utilities.css +1 -1
  299. package/dist/ui/components/BaseListingCard.d.ts +10 -0
  300. package/dist/ui/components/BaseListingCard.js +17 -1
  301. package/dist/ui/components/DetailPageGallery.d.ts +32 -0
  302. package/dist/ui/components/DetailPageGallery.js +47 -0
  303. package/dist/ui/components/DetailPageHero.d.ts +30 -0
  304. package/dist/ui/components/DetailPageHero.js +22 -0
  305. package/dist/ui/components/DetailPageTabs.d.ts +34 -0
  306. package/dist/ui/components/DetailPageTabs.js +38 -0
  307. package/dist/ui/components/HorizontalScroller.style.css +15 -2
  308. package/dist/ui/components/ListingLayout.d.ts +11 -2
  309. package/dist/ui/components/ListingLayout.js +12 -6
  310. package/dist/ui/components/PaginatedSelect.d.ts +66 -0
  311. package/dist/ui/components/PaginatedSelect.js +201 -0
  312. package/dist/ui/components/PaginatedSelect.style.css +254 -0
  313. package/dist/ui/components/Semantic.d.ts +0 -4
  314. package/dist/ui/components/Semantic.js +0 -2
  315. package/dist/ui/components/SettingsSection.d.ts +47 -0
  316. package/dist/ui/components/SettingsSection.js +38 -0
  317. package/dist/ui/components/index.style.css +1 -4
  318. package/dist/ui/index.d.ts +12 -14
  319. package/dist/ui/index.js +6 -7
  320. package/dist/utils/id-generators.d.ts +1 -18
  321. package/dist/utils/id-generators.js +51 -18
  322. package/dist/validation/schemas.d.ts +25 -0
  323. package/dist/validation/schemas.js +28 -0
  324. package/package.json +1 -1
@@ -241,7 +241,7 @@ export function SellerTemplatesView({ onDelete, onBulkDelete, onDuplicate, }) {
241
241
  }),
242
242
  ];
243
243
  useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: bulkActions } } : {});
244
- return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: filterActiveCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search templates by name...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: sort, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, showTableView: true, view: "table", onViewChange: () => { }, onResetAll: resetAll, hasActiveState: hasActiveState, extra: _jsxs(Button, { size: "sm", onClick: openCreate, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx("span", { children: "New Template" })] }) }), 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: safePage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), selection.selectedCount > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx(Div, { className: "mb-4 rounded-xl border border-red-200 bg-error-surface dark:border-red-900/60 px-4 py-3 text-sm text-error", children: errorMessage })), isLoading ? (_jsx(Div, { className: "space-y-2", children: Array.from({ length: 5 }).map((_, i) => (_jsx(Div, { className: "h-14 animate-pulse rounded-xl border border-zinc-100 dark:border-slate-700 bg-zinc-50 dark:bg-slate-800" }, i))) })) : pageRows.length === 0 ? (_jsx(Div, { className: "py-16 text-center", children: _jsx(Text, { className: "text-zinc-400 dark:text-zinc-400", children: q || conditionFilter
244
+ return (_jsxs("div", { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: filterActiveCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search templates by name...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: sort, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, showTableView: true, view: "table", onViewChange: () => { }, onResetAll: resetAll, hasActiveState: hasActiveState, extra: _jsxs(Button, { size: "sm", onClick: openCreate, className: "flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), _jsx("span", { children: "New Template" })] }) }), 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: safePage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), selection.selectedCount > 0 && (_jsx(BulkActionBar, { selectedCount: selection.selectedCount, actions: bulkActions, onClearSelection: selection.clearSelection })), _jsxs("div", { className: "py-4 px-3 sm:px-4", children: [errorMessage && (_jsx(Div, { className: "mb-4 rounded-xl border border-error/20 bg-error-surface px-4 py-3 text-sm text-error", children: errorMessage })), isLoading ? (_jsx(Div, { className: "space-y-2", children: Array.from({ length: 5 }).map((_, i) => (_jsx(Div, { className: "h-14 animate-pulse rounded-xl border border-zinc-100 dark:border-slate-700 bg-zinc-50 dark:bg-slate-800" }, i))) })) : pageRows.length === 0 ? (_jsx(Div, { className: "py-16 text-center", children: _jsx(Text, { className: "text-zinc-400 dark:text-zinc-400", children: q || conditionFilter
245
245
  ? "No templates match your search or filters"
246
246
  : "No templates yet — add your first product template" }) })) : (_jsx(DataTable, { columns: COLUMNS, data: pageRows, keyExtractor: (r) => r.id, selectable: bulkActions.length > 0, selectedIds: selection.selectedIds, onSelectionChange: (ids) => selection.setSelectedIds(ids), actions: (row) => (_jsx(RowActionMenu, { actions: [
247
247
  {
@@ -259,5 +259,5 @@ export function SellerTemplatesView({ onDelete, onBulkDelete, onDuplicate, }) {
259
259
  onClick: () => setDeleteTargetId(row.id),
260
260
  disabled: deletingId === row.id,
261
261
  },
262
- ] })) }))] }), _jsx(FilterDrawer, { open: filterOpen, onOpen: openFilters, onClose: () => setFilterOpen(false), onApply: applyFilters, onReset: () => setPendingCondition(""), activeCount: filterActiveCount, hideTrigger: true, children: _jsx(Div, { className: "space-y-4 p-4", children: _jsxs(Div, { children: [_jsx("label", { className: "mb-1.5 block text-sm font-medium text-zinc-700 dark:text-zinc-300", children: "Condition" }), _jsx(Select, { value: pendingCondition, onValueChange: setPendingCondition, options: CONDITION_OPTIONS })] }) }) }), _jsx(SideDrawer, { isOpen: drawerOpen, onClose: closeDrawer, title: drawerMode === "create" ? "New Template" : "Edit Template", mode: drawerMode, isDirty: draft.name !== "" || draft.category !== "" || draft.brand !== "", footer: _jsxs("div", { className: "flex items-center justify-end gap-2", children: [_jsx(Button, { size: "sm", variant: "ghost", onClick: closeDrawer, disabled: saving, children: "Cancel" }), _jsx(Button, { size: "sm", isLoading: saving, onClick: handleSave, children: drawerMode === "create" ? "Create Template" : "Save Changes" })] }), children: _jsxs(Stack, { gap: "md", children: [savingError && (_jsx(Div, { className: "rounded-lg border border-red-200 bg-error-surface dark:border-red-900/60 px-3 py-2 text-sm text-error", children: savingError })), _jsx(Input, { id: "tpl-name", label: "Template Name", value: draft.name, onChange: (e) => setDraft((d) => ({ ...d, name: e.target.value })), placeholder: "e.g. Pok\u00E9mon Card Standard", required: true, autoComplete: "off" }), _jsx(Input, { id: "tpl-description", label: "Description (optional)", value: draft.description, onChange: (e) => setDraft((d) => ({ ...d, description: e.target.value })), placeholder: "Short note about when to use this template", autoComplete: "off" }), _jsx(Input, { id: "tpl-category", label: "Category (optional)", value: draft.category, onChange: (e) => setDraft((d) => ({ ...d, category: e.target.value })), placeholder: "e.g. trading-cards", autoComplete: "off" }), _jsx(Input, { id: "tpl-brand", label: "Brand (optional)", value: draft.brand, onChange: (e) => setDraft((d) => ({ ...d, brand: e.target.value })), placeholder: "e.g. Pok\u00E9mon Company", autoComplete: "off" }), _jsx(Select, { label: "Condition (optional)", name: "tpl-condition", value: draft.condition, onValueChange: (v) => setDraft((d) => ({ ...d, condition: v })), options: CONDITION_OPTIONS })] }) }), deleteTargetId && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Template", message: "Are you sure you want to delete this template? This cannot be undone.", onConfirm: () => handleDelete(deleteTargetId), onClose: () => setDeleteTargetId(null), isDeleting: deletingId === deleteTargetId }))] }));
262
+ ] })) }))] }), _jsx(FilterDrawer, { open: filterOpen, onOpen: openFilters, onClose: () => setFilterOpen(false), onApply: applyFilters, onReset: () => setPendingCondition(""), activeCount: filterActiveCount, hideTrigger: true, children: _jsx(Div, { className: "space-y-4 p-4", children: _jsxs(Div, { children: [_jsx("label", { className: "mb-1.5 block text-sm font-medium text-zinc-700 dark:text-zinc-300", children: "Condition" }), _jsx(Select, { value: pendingCondition, onValueChange: setPendingCondition, options: CONDITION_OPTIONS })] }) }) }), _jsx(SideDrawer, { isOpen: drawerOpen, onClose: closeDrawer, title: drawerMode === "create" ? "New Template" : "Edit Template", mode: drawerMode, isDirty: draft.name !== "" || draft.category !== "" || draft.brand !== "", footer: _jsxs("div", { className: "flex items-center justify-end gap-2", children: [_jsx(Button, { size: "sm", variant: "ghost", onClick: closeDrawer, disabled: saving, children: "Cancel" }), _jsx(Button, { size: "sm", isLoading: saving, onClick: handleSave, children: drawerMode === "create" ? "Create Template" : "Save Changes" })] }), children: _jsxs(Stack, { gap: "md", children: [savingError && (_jsx(Div, { className: "rounded-lg border border-error/20 bg-error-surface px-3 py-2 text-sm text-error", children: savingError })), _jsx(Input, { id: "tpl-name", label: "Template Name", value: draft.name, onChange: (e) => setDraft((d) => ({ ...d, name: e.target.value })), placeholder: "e.g. Pok\u00E9mon Card Standard", required: true, autoComplete: "off" }), _jsx(Input, { id: "tpl-description", label: "Description (optional)", value: draft.description, onChange: (e) => setDraft((d) => ({ ...d, description: e.target.value })), placeholder: "Short note about when to use this template", autoComplete: "off" }), _jsx(Input, { id: "tpl-category", label: "Category (optional)", value: draft.category, onChange: (e) => setDraft((d) => ({ ...d, category: e.target.value })), placeholder: "e.g. trading-cards", autoComplete: "off" }), _jsx(Input, { id: "tpl-brand", label: "Brand (optional)", value: draft.brand, onChange: (e) => setDraft((d) => ({ ...d, brand: e.target.value })), placeholder: "e.g. Pok\u00E9mon Company", autoComplete: "off" }), _jsx(Select, { label: "Condition (optional)", name: "tpl-condition", value: draft.condition, onValueChange: (v) => setDraft((d) => ({ ...d, condition: v })), options: CONDITION_OPTIONS })] }) }), deleteTargetId && (_jsx(ConfirmDeleteModal, { isOpen: true, title: "Delete Template", message: "Are you sure you want to delete this template? This cannot be undone.", onConfirm: () => handleDelete(deleteTargetId), onClose: () => setDeleteTargetId(null), isDeleting: deletingId === deleteTargetId }))] }));
263
263
  }
@@ -1,4 +1,3 @@
1
1
  import type { SlottedListingViewProps } from "../../../ui";
2
- export interface SellersListViewProps extends SlottedListingViewProps {
3
- }
2
+ export type SellersListViewProps = SlottedListingViewProps;
4
3
  export declare function SellersListView(props: SellersListViewProps): import("react/jsx-runtime").JSX.Element;
@@ -1,4 +1,9 @@
1
1
  import type { SellerAnalyticsSummary } from "../../types";
2
+ /**
3
+ * W1-32 — SellerAnalyticsStats now composes AdminStatCard (the only live
4
+ * stat-card primitive after W1-30) instead of redefining its own inline
5
+ * StatCard. Same gradient presets, same visual identity.
6
+ */
2
7
  export interface SellerAnalyticsStatsLabels {
3
8
  totalRevenue?: string;
4
9
  totalOrders?: string;
@@ -2,13 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { TrendingUp, ShoppingBag, Package, CheckCircle } from "lucide-react";
4
4
  import { Div } from "../../../../ui";
5
- const GREEN_GRAD = "linear-gradient(135deg,var(--appkit-color-cobalt,#3570fc) 0%,var(--appkit-color-secondary-400,#84e122) 100%)";
6
- const BRAND_GRAD = "linear-gradient(135deg,var(--appkit-color-primary-700,#1343de) 0%,var(--appkit-color-cobalt,#3570fc) 55%,var(--appkit-color-secondary-400,#84e122) 100%)";
7
- const AMBER_GRAD = "linear-gradient(135deg,var(--appkit-color-amber-500,#f59e0b) 0%,var(--appkit-color-amber-600,#d97706) 100%)";
8
- const BLUE_GRAD = "linear-gradient(135deg,var(--appkit-color-primary-700,#1343de) 0%,var(--appkit-color-cobalt,#3570fc) 100%)";
9
- function StatCard({ label, value, gradient, Icon }) {
10
- return (_jsxs(Div, { className: "relative rounded-xl border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] overflow-hidden shadow-sm hover:shadow-md transition-shadow", children: [_jsx("div", { className: "absolute top-0 left-0 right-0 h-[3px]", style: { background: gradient }, "aria-hidden": "true" }), _jsxs(Div, { className: "px-5 pb-5 pt-6 flex items-start justify-between gap-3", children: [_jsxs(Div, { className: "min-w-0 flex-1", children: [_jsx("div", { className: "text-[11px] font-semibold uppercase tracking-widest text-[var(--appkit-color-text-muted)]", children: label }), _jsx("div", { className: "mt-2 text-2xl font-bold text-[var(--appkit-color-text)] tabular-nums leading-none", children: value })] }), _jsx("div", { className: "flex-shrink-0 w-10 h-10 rounded-lg flex items-center justify-center", style: { background: gradient }, children: _jsx(Icon, { className: "w-5 h-5 text-white" }) })] })] }));
11
- }
5
+ import { AdminStatCard } from "../../../admin/components/analytics/AdminStatCard";
12
6
  export function SellerAnalyticsStats({ summary, labels = {}, formatRevenue = (amount) => String(amount), className = "", }) {
13
- return (_jsxs(Div, { className: `grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-4 ${className}`, children: [_jsx(StatCard, { label: labels.totalRevenue ?? "Total Revenue", value: formatRevenue(summary.totalRevenue), gradient: GREEN_GRAD, Icon: TrendingUp }), _jsx(StatCard, { label: labels.totalOrders ?? "Total Orders", value: String(summary.totalOrders), gradient: BRAND_GRAD, Icon: ShoppingBag }), _jsx(StatCard, { label: labels.totalProducts ?? "Total Products", value: String(summary.totalProducts), gradient: AMBER_GRAD, Icon: Package }), _jsx(StatCard, { label: labels.publishedProducts ?? "Published", value: String(summary.publishedProducts), gradient: BLUE_GRAD, Icon: CheckCircle })] }));
7
+ return (_jsxs(Div, { className: `grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-4 ${className}`, children: [_jsx(AdminStatCard, { label: labels.totalRevenue ?? "Total Revenue", value: formatRevenue(summary.totalRevenue), gradient: "green", icon: _jsx(TrendingUp, { className: "w-5 h-5 text-white" }) }), _jsx(AdminStatCard, { label: labels.totalOrders ?? "Total Orders", value: String(summary.totalOrders), gradient: "brand", icon: _jsx(ShoppingBag, { className: "w-5 h-5 text-white" }) }), _jsx(AdminStatCard, { label: labels.totalProducts ?? "Total Products", value: String(summary.totalProducts), gradient: "amber", icon: _jsx(Package, { className: "w-5 h-5 text-white" }) }), _jsx(AdminStatCard, { label: labels.publishedProducts ?? "Published", value: String(summary.publishedProducts), gradient: "blue", icon: _jsx(CheckCircle, { className: "w-5 h-5 text-white" }) })] }));
14
8
  }
@@ -1,6 +1,3 @@
1
- export { SellerStatCard } from "./SellerStatCard";
2
- export { SellerSidebar } from "./SellerSidebar";
3
- export type { SellerNavItem } from "./SellerSidebar";
4
1
  export { SellerDashboardView } from "./SellerDashboardView";
5
2
  export type { SellerDashboardViewProps } from "./SellerDashboardView";
6
3
  export { SellerProductsView } from "./SellerProductsView";
@@ -1,5 +1,3 @@
1
- export { SellerStatCard } from "./SellerStatCard";
2
- export { SellerSidebar } from "./SellerSidebar";
3
1
  export { SellerDashboardView } from "./SellerDashboardView";
4
2
  export { SellerProductsView } from "./SellerProductsView";
5
3
  export { SellerAuctionsView } from "./SellerAuctionsView";
@@ -4,7 +4,6 @@
4
4
  * Server-only entry point for seller repositories and API route handlers.
5
5
  */
6
6
  export * from "./actions";
7
- export { SellerRepository, PayoutsRepository, } from "./repository/seller.repository";
8
7
  export { OfferRepository, offerRepository, } from "./repository/offer.repository";
9
8
  export { GET as sellerProductsGET } from "./api/products/route";
10
9
  export { GET as sellerStoreGET } from "./api/store/route";
@@ -4,7 +4,6 @@
4
4
  * Server-only entry point for seller repositories and API route handlers.
5
5
  */
6
6
  export * from "./actions";
7
- export { SellerRepository, PayoutsRepository, } from "./repository/seller.repository";
8
7
  export { OfferRepository, offerRepository, } from "./repository/offer.repository";
9
8
  export { GET as sellerProductsGET } from "./api/products/route";
10
9
  export { GET as sellerStoreGET } from "./api/store/route";
@@ -40,4 +40,4 @@ export interface UseFormShellResult {
40
40
  markClean: () => void;
41
41
  }
42
42
  export declare function useFormShell(): UseFormShellResult;
43
- export declare function FormShell({ isOpen, onClose, title, breadcrumb, isDirty, isLoading, sections, onSaveDraft, onPublish, saveLabel, publishLabel, renderBottomBar, previewSlot, splitPreview, children, }: FormShellProps): import("react/jsx-runtime").JSX.Element | null;
43
+ export declare function FormShell({ isOpen, onClose, title, breadcrumb, isDirty, isLoading, sections, onSaveDraft, onPublish, saveLabel, publishLabel, renderBottomBar, previewSlot, splitPreview: splitPreviewProp, children, }: FormShellProps): import("react/jsx-runtime").JSX.Element | null;
@@ -5,7 +5,7 @@ import { X, AlertTriangle, Eye, ArrowLeft } from "lucide-react";
5
5
  import { Button } from "../../ui/components/Button";
6
6
  import { classNames } from "../../ui/style.helper";
7
7
  import { FORM_ACTION_META, FORM_ACTION_ID } from "../products/constants/action-defs";
8
- import { Text } from "../../ui";
8
+ import { Div, Row, Span, Stack, Text } from "../../ui";
9
9
  export function useFormShell() {
10
10
  const [isDirty, setIsDirty] = useState(false);
11
11
  return {
@@ -15,7 +15,10 @@ export function useFormShell() {
15
15
  };
16
16
  }
17
17
  const FOCUSABLE = 'a[href],button:not([disabled]),textarea:not([disabled]),input:not([disabled]),select:not([disabled]),[tabindex]:not([tabindex="-1"])';
18
- export function FormShell({ isOpen, onClose, title, breadcrumb, isDirty = false, isLoading = false, sections, onSaveDraft, onPublish, saveLabel = FORM_ACTION_META[FORM_ACTION_ID.SAVE_DRAFT].label, publishLabel = FORM_ACTION_META[FORM_ACTION_ID.PUBLISH].label, renderBottomBar, previewSlot, splitPreview = false, children, }) {
18
+ export function FormShell({ isOpen, onClose, title, breadcrumb, isDirty = false, isLoading = false, sections, onSaveDraft, onPublish, saveLabel = FORM_ACTION_META[FORM_ACTION_ID.SAVE_DRAFT].label, publishLabel = FORM_ACTION_META[FORM_ACTION_ID.PUBLISH].label, renderBottomBar, previewSlot, splitPreview: splitPreviewProp, children, }) {
19
+ // W1-37: auto-enable splitPreview when a previewSlot is provided. Callers
20
+ // can still pass splitPreview={false} explicitly to opt out.
21
+ const splitPreview = splitPreviewProp ?? Boolean(previewSlot);
19
22
  const panelRef = useRef(null);
20
23
  const bodyRef = useRef(null);
21
24
  const [showUnsaved, setShowUnsaved] = useState(false);
@@ -102,8 +105,8 @@ export function FormShell({ isOpen, onClose, title, breadcrumb, isDirty = false,
102
105
  };
103
106
  if (!isOpen)
104
107
  return null;
105
- return (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 bg-black/50 backdrop-blur-[2px]", style: { zIndex: "calc(var(--appkit-z-modal) - 1)" }, "aria-hidden": "true", onClick: attemptClose }), _jsxs("div", { ref: panelRef, role: "dialog", "aria-modal": "true", "aria-label": title, className: "fixed top-0 bottom-0 left-0 right-0 lg:left-[10%] lg:right-[10%] flex flex-col bg-[var(--appkit-color-surface)] shadow-2xl", style: { zIndex: "var(--appkit-z-modal)" }, children: [_jsxs("div", { className: "flex-shrink-0 sticky top-0 z-10 border-b border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-5 py-3 flex items-center gap-3", children: [previewMode ? (_jsxs("button", { type: "button", onClick: () => setPreviewMode(false), "aria-label": "Back to edit", className: "rounded-lg p-1.5 text-[var(--appkit-color-text-muted)] hover:bg-[var(--appkit-color-border-subtle)] transition-colors flex-shrink-0 flex items-center gap-1.5 text-sm", children: [_jsx(ArrowLeft, { className: "w-4 h-4" }), _jsx("span", { className: "hidden sm:inline", children: "Back to Edit" })] })) : (_jsx("button", { type: "button", onClick: attemptClose, "aria-label": "Close", className: "rounded-lg p-1.5 text-[var(--appkit-color-text-muted)] hover:bg-[var(--appkit-color-border-subtle)] transition-colors flex-shrink-0", children: _jsx(X, { className: "w-5 h-5" }) })), _jsxs("div", { className: "flex-1 min-w-0", children: [breadcrumb && (_jsx(Text, { className: "text-xs text-[var(--appkit-color-text-muted)] truncate mb-0.5", children: breadcrumb })), _jsx(Text, { className: "text-sm font-semibold text-[var(--appkit-color-text)] truncate", children: previewMode ? `Preview — ${title}` : title })] }), _jsx("div", { className: "flex items-center gap-2 flex-shrink-0", children: previewMode ? null : (_jsxs(_Fragment, { children: [previewSlot && (_jsxs("button", { type: "button", onClick: () => setPreviewMode(true), className: "flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm text-[var(--appkit-color-text-muted)] hover:bg-[var(--appkit-color-border-subtle)] transition-colors border border-[var(--appkit-color-border)]", children: [_jsx(Eye, { className: "w-4 h-4" }), _jsx("span", { className: "hidden sm:inline", children: "Preview" })] })), onSaveDraft && (_jsx(Button, { variant: "outline", size: "sm", onClick: handleSaveDraft, disabled: isLoading || savingDraft || publishing, isLoading: savingDraft, children: saveLabel })), onPublish && (_jsx(Button, { variant: "primary", size: "sm", onClick: handlePublish, disabled: isLoading || savingDraft || publishing, isLoading: publishing, children: publishLabel }))] })) })] }), _jsxs("div", { className: "flex flex-1 overflow-hidden", children: [sections && sections.length > 0 && !previewMode && (_jsx("nav", { "aria-label": "Form sections", className: "hidden lg:flex flex-col flex-shrink-0 w-48 border-r border-[var(--appkit-color-border)] py-4 px-3 gap-1 overflow-y-auto", children: sections.map((sec) => (_jsx("button", { type: "button", onClick: () => scrollToSection(sec.id), className: "text-left text-sm px-3 py-2 rounded-lg text-[var(--appkit-color-text-muted)] hover:text-[var(--appkit-color-text)] hover:bg-[var(--appkit-color-border-subtle)] transition-colors", children: sec.label }, sec.id))) })), sections && sections.length > 0 && !previewMode && (_jsx("div", { className: "lg:hidden fixed top-[var(--form-shell-topbar-h,57px)] left-0 right-0 z-10 flex overflow-x-auto gap-1 px-5 py-2 bg-[var(--appkit-color-surface)] border-b border-[var(--appkit-color-border)]", children: sections.map((sec) => (_jsx("button", { type: "button", onClick: () => scrollToSection(sec.id), className: "flex-shrink-0 text-xs px-3 py-1.5 rounded-full border border-[var(--appkit-color-border)] text-[var(--appkit-color-text-muted)] hover:border-[var(--appkit-color-primary)] hover:text-[var(--appkit-color-primary)] transition-colors whitespace-nowrap", children: sec.label }, sec.id))) })), _jsx("div", { ref: bodyRef, className: classNames("flex-1 overflow-y-auto", sections && sections.length > 0 && !previewMode ? "pt-0 lg:pt-0" : ""), children: previewMode && previewSlot ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "sticky top-0 z-10 flex items-center gap-2 bg-[var(--appkit-color-warning-surface)] border-b border-[var(--appkit-color-warning)] px-4 py-2 text-sm text-[var(--appkit-color-warning-text,var(--appkit-color-warning))]", children: [_jsx(Eye, { className: "w-4 h-4 flex-shrink-0" }), _jsx("span", { children: "Preview \u2014 not visible to buyers until published" })] }), _jsx("div", { className: "py-4", children: previewSlot() })] })) : splitPreview && previewSlot ? (
108
+ return (_jsxs(_Fragment, { children: [_jsx(Div, { className: "fixed inset-0 bg-black/50 backdrop-blur-[2px]", style: { zIndex: "calc(var(--appkit-z-modal) - 1)" }, "aria-hidden": "true", onClick: attemptClose }), _jsxs(Div, { ref: panelRef, role: "dialog", "aria-modal": "true", "aria-label": title, className: "fixed top-0 bottom-0 left-0 right-0 lg:left-[10%] lg:right-[10%] flex flex-col bg-[var(--appkit-color-surface)] shadow-2xl", style: { zIndex: "var(--appkit-z-modal)" }, children: [_jsxs(Row, { gap: "sm", className: "flex-shrink-0 sticky top-0 z-10 border-b border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-5 py-3", children: [previewMode ? (_jsxs("button", { type: "button", onClick: () => setPreviewMode(false), "aria-label": "Back to edit", className: "rounded-lg p-1.5 text-[var(--appkit-color-text-muted)] hover:bg-[var(--appkit-color-border-subtle)] transition-colors flex-shrink-0 flex items-center gap-1.5 text-sm", children: [_jsx(ArrowLeft, { className: "w-4 h-4" }), _jsx(Span, { className: "hidden sm:inline", children: "Back to Edit" })] })) : (_jsx("button", { type: "button", onClick: attemptClose, "aria-label": "Close", className: "rounded-lg p-1.5 text-[var(--appkit-color-text-muted)] hover:bg-[var(--appkit-color-border-subtle)] transition-colors flex-shrink-0", children: _jsx(X, { className: "w-5 h-5" }) })), _jsxs(Div, { className: "flex-1 min-w-0", children: [breadcrumb && (_jsx(Text, { className: "text-xs text-[var(--appkit-color-text-muted)] truncate mb-0.5", children: breadcrumb })), _jsx(Text, { className: "text-sm font-semibold text-[var(--appkit-color-text)] truncate", children: previewMode ? `Preview — ${title}` : title })] }), _jsx(Row, { gap: "xs", className: "flex-shrink-0", children: previewMode ? null : (_jsxs(_Fragment, { children: [previewSlot && (_jsxs("button", { type: "button", onClick: () => setPreviewMode(true), className: "flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm text-[var(--appkit-color-text-muted)] hover:bg-[var(--appkit-color-border-subtle)] transition-colors border border-[var(--appkit-color-border)]", children: [_jsx(Eye, { className: "w-4 h-4" }), _jsx(Span, { className: "hidden sm:inline", children: "Preview" })] })), onSaveDraft && (_jsx(Button, { variant: "outline", size: "sm", onClick: handleSaveDraft, disabled: isLoading || savingDraft || publishing, isLoading: savingDraft, children: saveLabel })), onPublish && (_jsx(Button, { variant: "primary", size: "sm", onClick: handlePublish, disabled: isLoading || savingDraft || publishing, isLoading: publishing, children: publishLabel }))] })) })] }), _jsxs(Div, { className: "flex flex-1 overflow-hidden", children: [sections && sections.length > 0 && !previewMode && (_jsx("nav", { "aria-label": "Form sections", className: "hidden lg:flex flex-col flex-shrink-0 w-48 border-r border-[var(--appkit-color-border)] py-4 px-3 gap-1 overflow-y-auto", children: sections.map((sec) => (_jsx("button", { type: "button", onClick: () => scrollToSection(sec.id), className: "text-left text-sm px-3 py-2 rounded-lg text-[var(--appkit-color-text-muted)] hover:text-[var(--appkit-color-text)] hover:bg-[var(--appkit-color-border-subtle)] transition-colors", children: sec.label }, sec.id))) })), sections && sections.length > 0 && !previewMode && (_jsx(Row, { gap: "px", className: "lg:hidden fixed top-[var(--form-shell-topbar-h,57px)] left-0 right-0 z-10 overflow-x-auto px-5 py-2 bg-[var(--appkit-color-surface)] border-b border-[var(--appkit-color-border)]", children: sections.map((sec) => (_jsx("button", { type: "button", onClick: () => scrollToSection(sec.id), className: "flex-shrink-0 text-xs px-3 py-1.5 rounded-full border border-[var(--appkit-color-border)] text-[var(--appkit-color-text-muted)] hover:border-[var(--appkit-color-primary)] hover:text-[var(--appkit-color-primary)] transition-colors whitespace-nowrap", children: sec.label }, sec.id))) })), _jsx(Div, { ref: bodyRef, className: classNames("flex-1 overflow-y-auto", sections && sections.length > 0 && !previewMode ? "pt-0 lg:pt-0" : ""), children: previewMode && previewSlot ? (_jsxs(_Fragment, { children: [_jsxs(Row, { gap: "xs", className: "sticky top-0 z-10 bg-[var(--appkit-color-warning-surface)] border-b border-[var(--appkit-color-warning)] px-4 py-2 text-sm text-[var(--appkit-color-warning-text,var(--appkit-color-warning))]", children: [_jsx(Eye, { className: "w-4 h-4 flex-shrink-0" }), _jsx(Span, { children: "Preview \u2014 not visible to buyers until published" })] }), _jsx(Div, { className: "py-4", children: previewSlot() })] })) : splitPreview && previewSlot ? (
106
109
  // S-STORE-3-D — desktop 60/40 split: form left, preview right.
107
110
  // Below `lg`, falls back to single-column form (preview-as-modal via existing toggle).
108
- _jsxs("div", { className: "lg:grid lg:grid-cols-[3fr_2fr] lg:gap-6 lg:px-6 lg:py-6 lg:max-w-[1400px] lg:mx-auto", children: [_jsx("div", { className: "max-w-3xl mx-auto px-5 py-6 sm:px-6 lg:max-w-none lg:px-0 lg:py-0", children: children }), _jsxs("div", { className: "hidden lg:block sticky lg:top-4 lg:self-start lg:max-h-[calc(100vh-6rem)] overflow-y-auto border border-[var(--appkit-color-border)] rounded-lg bg-[var(--appkit-color-surface-raised)] p-4", children: [_jsxs("div", { className: "flex items-center gap-2 mb-3 text-xs font-semibold uppercase tracking-wide text-[var(--appkit-color-text-muted)]", children: [_jsx(Eye, { className: "w-3.5 h-3.5" }), _jsx("span", { children: "Live preview" })] }), previewSlot()] })] })) : (_jsx("div", { className: "max-w-3xl mx-auto px-5 py-6 sm:px-6", children: children })) })] }), !previewMode && renderBottomBar ? (renderBottomBar()) : !previewMode && (onSaveDraft || onPublish) ? (_jsxs("div", { className: "flex-shrink-0 sticky bottom-0 z-10 border-t border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-5 py-3 flex items-center justify-between", children: [_jsx(Button, { variant: "ghost", size: "sm", onClick: attemptClose, disabled: isLoading, children: FORM_ACTION_META[FORM_ACTION_ID.DISCARD].label }), _jsxs("div", { className: "flex items-center gap-2", children: [onSaveDraft && (_jsx(Button, { variant: "outline", size: "sm", onClick: handleSaveDraft, disabled: isLoading || savingDraft || publishing, isLoading: savingDraft, children: saveLabel })), onPublish && (_jsxs(Button, { variant: "primary", size: "sm", onClick: handlePublish, disabled: isLoading || savingDraft || publishing, isLoading: publishing, children: [publishLabel, " \u2192"] }))] })] })) : null] }), showUnsaved && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 bg-black/60", style: { zIndex: "calc(var(--appkit-z-modal) + 5)" }, onClick: () => setShowUnsaved(false) }), _jsxs("div", { className: "fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[90vw] max-w-sm bg-[var(--appkit-color-surface)] rounded-xl shadow-2xl p-6", style: { zIndex: "calc(var(--appkit-z-modal) + 5)" }, children: [_jsxs("div", { className: "flex gap-3 mb-4", children: [_jsx("span", { className: "flex-shrink-0 w-10 h-10 rounded-full bg-[var(--appkit-color-warning-surface)] flex items-center justify-center", children: _jsx(AlertTriangle, { className: "w-5 h-5 text-[var(--appkit-color-warning)]" }) }), _jsxs(_Fragment, { children: [_jsx(Text, { className: "font-semibold text-[var(--appkit-color-text)]", children: "Unsaved changes" }), _jsx(Text, { className: "text-sm text-[var(--appkit-color-text-muted)] mt-1", children: "You have unsaved changes. Leave without saving?" })] })] }), _jsxs("div", { className: "flex gap-2 justify-end", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: () => setShowUnsaved(false), children: "Stay" }), _jsx(Button, { variant: "danger", size: "sm", onClick: () => { setShowUnsaved(false); onClose(); }, children: "Leave" })] })] })] }))] }));
111
+ _jsxs(Div, { className: "lg:grid lg:grid-cols-[3fr_2fr] lg:gap-6 lg:px-6 lg:py-6 lg:max-w-[1400px] lg:mx-auto", children: [_jsx(Div, { className: "max-w-3xl mx-auto px-5 py-6 sm:px-6 lg:max-w-none lg:px-0 lg:py-0", children: children }), _jsxs(Div, { className: "hidden lg:block sticky lg:top-4 lg:self-start lg:max-h-[calc(100vh-6rem)] overflow-y-auto border border-[var(--appkit-color-border)] rounded-lg bg-[var(--appkit-color-surface-raised)] p-4", children: [_jsxs(Row, { gap: "xs", className: "mb-3 text-xs font-semibold uppercase tracking-wide text-[var(--appkit-color-text-muted)]", children: [_jsx(Eye, { className: "w-3.5 h-3.5" }), _jsx(Span, { children: "Live preview" })] }), previewSlot()] })] })) : (_jsx(Div, { className: "max-w-3xl mx-auto px-5 py-6 sm:px-6", children: children })) })] }), !previewMode && renderBottomBar ? (renderBottomBar()) : !previewMode && (onSaveDraft || onPublish) ? (_jsxs(Row, { justify: "between", className: "flex-shrink-0 sticky bottom-0 z-10 border-t border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] px-5 py-3", children: [_jsx(Button, { variant: "ghost", size: "sm", onClick: attemptClose, disabled: isLoading, children: FORM_ACTION_META[FORM_ACTION_ID.DISCARD].label }), _jsxs(Row, { gap: "xs", children: [onSaveDraft && (_jsx(Button, { variant: "outline", size: "sm", onClick: handleSaveDraft, disabled: isLoading || savingDraft || publishing, isLoading: savingDraft, children: saveLabel })), onPublish && (_jsxs(Button, { variant: "primary", size: "sm", onClick: handlePublish, disabled: isLoading || savingDraft || publishing, isLoading: publishing, children: [publishLabel, " \u2192"] }))] })] })) : null] }), showUnsaved && (_jsxs(_Fragment, { children: [_jsx(Div, { className: "fixed inset-0 bg-black/60", style: { zIndex: "calc(var(--appkit-z-modal) + 5)" }, onClick: () => setShowUnsaved(false) }), _jsxs(Div, { className: "fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[90vw] max-w-sm bg-[var(--appkit-color-surface)] rounded-xl shadow-2xl p-6", style: { zIndex: "calc(var(--appkit-z-modal) + 5)" }, children: [_jsxs(Row, { gap: "sm", align: "start", className: "mb-4", children: [_jsx(Span, { className: "flex-shrink-0 w-10 h-10 rounded-full bg-[var(--appkit-color-warning-surface)] flex items-center justify-center", children: _jsx(AlertTriangle, { className: "w-5 h-5 text-[var(--appkit-color-warning)]" }) }), _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { className: "font-semibold text-[var(--appkit-color-text)]", children: "Unsaved changes" }), _jsx(Text, { className: "text-sm text-[var(--appkit-color-text-muted)]", children: "You have unsaved changes. Leave without saving?" })] })] }), _jsxs(Row, { gap: "xs", justify: "end", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: () => setShowUnsaved(false), children: "Stay" }), _jsx(Button, { variant: "danger", size: "sm", onClick: () => { setShowUnsaved(false); onClose(); }, children: "Leave" })] })] })] }))] }));
109
112
  }
@@ -0,0 +1,18 @@
1
+ import { type ReactNode } from "react";
2
+ export interface ImageFieldGroupProps {
3
+ /** Slot for the hero / cover image input — wire your own ImageUpload here. */
4
+ heroSlot?: ReactNode;
5
+ /** Slot for an additional gallery input (e.g. MediaUploadField with multi-image). */
6
+ gallerySlot?: ReactNode;
7
+ /** Optional section label override. */
8
+ sectionTitle?: ReactNode;
9
+ sectionDescription?: ReactNode;
10
+ }
11
+ /**
12
+ * `ImageFieldGroup` — wraps hero + gallery image slots in a `SettingsSection`.
13
+ * The actual `<ImageUpload>` / `<MediaUploadField>` instances stay with the
14
+ * consumer because their `onUpload` / context wiring is form-specific.
15
+ *
16
+ * W1-15 — extracted 2026-05-23.
17
+ */
18
+ export declare function ImageFieldGroup({ heroSlot, gallerySlot, sectionTitle, sectionDescription, }: ImageFieldGroupProps): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,15 @@
1
+ "use client";
2
+ import { jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { SettingsSection } from "../../../ui/components/SettingsSection";
4
+ /**
5
+ * `ImageFieldGroup` — wraps hero + gallery image slots in a `SettingsSection`.
6
+ * The actual `<ImageUpload>` / `<MediaUploadField>` instances stay with the
7
+ * consumer because their `onUpload` / context wiring is form-specific.
8
+ *
9
+ * W1-15 — extracted 2026-05-23.
10
+ */
11
+ export function ImageFieldGroup({ heroSlot, gallerySlot, sectionTitle = "Images", sectionDescription, }) {
12
+ if (!heroSlot && !gallerySlot)
13
+ return null;
14
+ return (_jsxs(SettingsSection, { title: sectionTitle, description: sectionDescription, children: [heroSlot, gallerySlot] }));
15
+ }
@@ -0,0 +1,22 @@
1
+ import { type ReactNode } from "react";
2
+ export interface SeoFieldGroupProps {
3
+ seoTitle: string;
4
+ seoDescription: string;
5
+ slug: string;
6
+ onSeoTitleChange: (next: string) => void;
7
+ onSeoDescriptionChange: (next: string) => void;
8
+ onSlugChange?: (next: string) => void;
9
+ /** Read-only computed canonical URL preview (e.g. `https://letitrip.in/products/<slug>`). */
10
+ canonicalPreview?: string;
11
+ /** Optional section label override. */
12
+ sectionTitle?: ReactNode;
13
+ sectionDescription?: ReactNode;
14
+ disabled?: boolean;
15
+ }
16
+ /**
17
+ * `SeoFieldGroup` — shared SEO inputs (title / description / slug) used across
18
+ * Product, Blog, Category, FAQ editors.
19
+ *
20
+ * W1-15 — extracted 2026-05-23.
21
+ */
22
+ export declare function SeoFieldGroup({ seoTitle, seoDescription, slug, onSeoTitleChange, onSeoDescriptionChange, onSlugChange, canonicalPreview, sectionTitle, sectionDescription, disabled, }: SeoFieldGroupProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,16 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Input } from "../../../ui/components/Input";
4
+ import { Textarea } from "../../../ui/components/Textarea";
5
+ import { SettingsSection } from "../../../ui/components/SettingsSection";
6
+ const SEO_TITLE_MAX = 60;
7
+ const SEO_DESC_MAX = 160;
8
+ /**
9
+ * `SeoFieldGroup` — shared SEO inputs (title / description / slug) used across
10
+ * Product, Blog, Category, FAQ editors.
11
+ *
12
+ * W1-15 — extracted 2026-05-23.
13
+ */
14
+ export function SeoFieldGroup({ seoTitle, seoDescription, slug, onSeoTitleChange, onSeoDescriptionChange, onSlugChange, canonicalPreview, sectionTitle = "SEO", sectionDescription = "Override the auto-generated metadata if needed. Leave blank to use defaults.", disabled = false, }) {
15
+ return (_jsxs(SettingsSection, { title: sectionTitle, description: sectionDescription, children: [_jsx(Input, { label: "SEO title", value: seoTitle, onChange: (e) => onSeoTitleChange(e.target.value), placeholder: "Falls back to the page title", maxLength: SEO_TITLE_MAX, helperText: `Max ${SEO_TITLE_MAX} characters.`, disabled: disabled }), _jsx(Textarea, { label: "SEO description", value: seoDescription, onChange: (e) => onSeoDescriptionChange(e.target.value), placeholder: "Falls back to the page description", maxLength: SEO_DESC_MAX, helperText: `Max ${SEO_DESC_MAX} characters.`, rows: 3, disabled: disabled }), onSlugChange ? (_jsx(Input, { label: "URL slug", value: slug, onChange: (e) => onSlugChange(e.target.value), disabled: disabled, helperText: canonicalPreview ? `Canonical: ${canonicalPreview}` : undefined })) : null] }));
16
+ }
@@ -0,0 +1,35 @@
1
+ import { type ReactNode } from "react";
2
+ export interface StatusFieldGroupOption<T extends string = string> {
3
+ value: T;
4
+ label: string;
5
+ description?: string;
6
+ }
7
+ export interface StatusFieldGroupProps<T extends string = string> {
8
+ /** Current status value. */
9
+ status: T;
10
+ /** Available status options. */
11
+ options: readonly StatusFieldGroupOption<T>[];
12
+ /** Setter. */
13
+ onStatusChange: (next: T) => void;
14
+ /** Optional sub-toggles below the status select (e.g. `isFeatured`, `isPromoted`). */
15
+ toggles?: ReadonlyArray<{
16
+ key: string;
17
+ label: ReactNode;
18
+ description?: ReactNode;
19
+ checked: boolean;
20
+ onChange: (next: boolean) => void;
21
+ disabled?: boolean;
22
+ }>;
23
+ /** Optional section label override. */
24
+ sectionTitle?: ReactNode;
25
+ sectionDescription?: ReactNode;
26
+ disabled?: boolean;
27
+ }
28
+ /**
29
+ * `StatusFieldGroup` — status select plus optional sub-toggles (featured /
30
+ * promoted / pinned, etc.) used across Product, Blog, Event, Coupon, FAQ
31
+ * editors.
32
+ *
33
+ * W1-15 — extracted 2026-05-23.
34
+ */
35
+ export declare function StatusFieldGroup<T extends string = string>({ status, options, onStatusChange, toggles, sectionTitle, sectionDescription, disabled, }: StatusFieldGroupProps<T>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,16 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Select } from "../../../ui/components/Select";
4
+ import { ToggleRow, SettingsSection } from "../../../ui/components/SettingsSection";
5
+ /**
6
+ * `StatusFieldGroup` — status select plus optional sub-toggles (featured /
7
+ * promoted / pinned, etc.) used across Product, Blog, Event, Coupon, FAQ
8
+ * editors.
9
+ *
10
+ * W1-15 — extracted 2026-05-23.
11
+ */
12
+ export function StatusFieldGroup({ status, options, onStatusChange, toggles, sectionTitle = "Status", sectionDescription, disabled = false, }) {
13
+ return (_jsxs(SettingsSection, { title: sectionTitle, description: sectionDescription, children: [_jsx(Select, { label: "Visibility status", value: status, onValueChange: (v) => onStatusChange(v), options: options.map((o) => ({ value: o.value, label: o.label })), disabled: disabled }), toggles?.length
14
+ ? toggles.map((t) => (_jsx(ToggleRow, { label: t.label, description: t.description, checked: t.checked, onChange: t.onChange, disabled: t.disabled ?? disabled }, t.key)))
15
+ : null] }));
16
+ }
@@ -0,0 +1,40 @@
1
+ import { type ReactNode } from "react";
2
+ export interface TitleDescriptionGroupProps {
3
+ /** Form field value: title. */
4
+ title: string;
5
+ /** Form field value: description (plain text). */
6
+ description: string;
7
+ /** Setters. */
8
+ onTitleChange: (next: string) => void;
9
+ onDescriptionChange: (next: string) => void;
10
+ /** Optional section label override. */
11
+ sectionTitle?: ReactNode;
12
+ /** Optional section description. */
13
+ sectionDescription?: ReactNode;
14
+ /** Optional placeholder overrides. */
15
+ titlePlaceholder?: string;
16
+ descriptionPlaceholder?: string;
17
+ /** Disable both inputs. */
18
+ disabled?: boolean;
19
+ /** When true, render a rich-text editor instead of plain `<Textarea>` (consumer-provided). */
20
+ renderDescription?: (args: {
21
+ value: string;
22
+ onChange: (next: string) => void;
23
+ disabled: boolean;
24
+ }) => ReactNode;
25
+ /** Field-level validation messages. */
26
+ titleError?: string;
27
+ descriptionError?: string;
28
+ /** Max length helpers. */
29
+ titleMaxLength?: number;
30
+ descriptionMaxLength?: number;
31
+ }
32
+ /**
33
+ * `TitleDescriptionGroup` — shared title + description fields used across
34
+ * Product, Blog, Category, Event, FAQ, Feature, Brand editors. Optionally
35
+ * accepts a `renderDescription` slot to plug in the rich-text editor without
36
+ * coupling this primitive to it.
37
+ *
38
+ * W1-15 — extracted 2026-05-23.
39
+ */
40
+ export declare function TitleDescriptionGroup({ title, description, onTitleChange, onDescriptionChange, sectionTitle, sectionDescription, titlePlaceholder, descriptionPlaceholder, disabled, renderDescription, titleError, descriptionError, titleMaxLength, descriptionMaxLength, }: TitleDescriptionGroupProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,16 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Input } from "../../../ui/components/Input";
4
+ import { Textarea } from "../../../ui/components/Textarea";
5
+ import { SettingsSection } from "../../../ui/components/SettingsSection";
6
+ /**
7
+ * `TitleDescriptionGroup` — shared title + description fields used across
8
+ * Product, Blog, Category, Event, FAQ, Feature, Brand editors. Optionally
9
+ * accepts a `renderDescription` slot to plug in the rich-text editor without
10
+ * coupling this primitive to it.
11
+ *
12
+ * W1-15 — extracted 2026-05-23.
13
+ */
14
+ export function TitleDescriptionGroup({ title, description, onTitleChange, onDescriptionChange, sectionTitle = "Title & description", sectionDescription, titlePlaceholder, descriptionPlaceholder, disabled = false, renderDescription, titleError, descriptionError, titleMaxLength, descriptionMaxLength, }) {
15
+ return (_jsxs(SettingsSection, { title: sectionTitle, description: sectionDescription, children: [_jsx(Input, { label: "Title", value: title, onChange: (e) => onTitleChange(e.target.value), placeholder: titlePlaceholder, disabled: disabled, maxLength: titleMaxLength, error: titleError, required: true }), renderDescription ? (renderDescription({ value: description, onChange: onDescriptionChange, disabled })) : (_jsx(Textarea, { label: "Description", value: description, onChange: (e) => onDescriptionChange(e.target.value), placeholder: descriptionPlaceholder, disabled: disabled, maxLength: descriptionMaxLength, error: descriptionError, rows: 5 }))] }));
16
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Field-group primitives (W1-15) — composable form sections used across the
3
+ * admin/seller editor surface. Each group is a thin wrapper around primitive
4
+ * inputs that encapsulates a recurring 3-or-more-field pattern.
5
+ */
6
+ export type { TitleDescriptionGroupProps } from "./TitleDescriptionGroup";
7
+ export { TitleDescriptionGroup } from "./TitleDescriptionGroup";
8
+ export type { ImageFieldGroupProps } from "./ImageFieldGroup";
9
+ export { ImageFieldGroup } from "./ImageFieldGroup";
10
+ export type { SeoFieldGroupProps } from "./SeoFieldGroup";
11
+ export { SeoFieldGroup } from "./SeoFieldGroup";
12
+ export type { StatusFieldGroupProps, StatusFieldGroupOption } from "./StatusFieldGroup";
13
+ export { StatusFieldGroup } from "./StatusFieldGroup";
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Field-group primitives (W1-15) — composable form sections used across the
3
+ * admin/seller editor surface. Each group is a thin wrapper around primitive
4
+ * inputs that encapsulates a recurring 3-or-more-field pattern.
5
+ */
6
+ export { TitleDescriptionGroup } from "./TitleDescriptionGroup";
7
+ export { ImageFieldGroup } from "./ImageFieldGroup";
8
+ export { SeoFieldGroup } from "./SeoFieldGroup";
9
+ export { StatusFieldGroup } from "./StatusFieldGroup";
@@ -4,3 +4,5 @@ export type { QuickFieldType, QuickFieldDef, QuickFormDrawerProps } from "./Quic
4
4
  export { QuickFormDrawer } from "./QuickFormDrawer";
5
5
  export type { StepDef, StepFormProps, StepFormActionsProps } from "./StepForm";
6
6
  export { StepForm, StepFormActions, StepIndicator } from "./StepForm";
7
+ export type { TitleDescriptionGroupProps, ImageFieldGroupProps, SeoFieldGroupProps, StatusFieldGroupProps, StatusFieldGroupOption, } from "./field-groups";
8
+ export { TitleDescriptionGroup, ImageFieldGroup, SeoFieldGroup, StatusFieldGroup, } from "./field-groups";
@@ -1,3 +1,4 @@
1
1
  export { FormShell, useFormShell } from "./FormShell";
2
2
  export { QuickFormDrawer } from "./QuickFormDrawer";
3
3
  export { StepForm, StepFormActions, StepIndicator } from "./StepForm";
4
+ export { TitleDescriptionGroup, ImageFieldGroup, SeoFieldGroup, StatusFieldGroup, } from "./field-groups";
@@ -1,3 +1,2 @@
1
- export interface StoreCapabilitiesGuideViewProps {
2
- }
1
+ export type StoreCapabilitiesGuideViewProps = Record<string, never>;
3
2
  export declare function StoreCapabilitiesGuideView(_props: StoreCapabilitiesGuideViewProps): import("react/jsx-runtime").JSX.Element;
@@ -1,3 +1,2 @@
1
- export interface StoreFinanceGuideViewProps {
2
- }
1
+ export type StoreFinanceGuideViewProps = Record<string, never>;
3
2
  export declare function StoreFinanceGuideView(_props: StoreFinanceGuideViewProps): import("react/jsx-runtime").JSX.Element;
@@ -2,8 +2,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Button, Div, Heading, RichText, Row, Section, Span, Text, } from "../../../ui";
3
3
  import { normalizeRichTextHtml } from "../../../utils/string.formatter";
4
4
  import { ShareButton } from "../../products/components/ShareButton";
5
+ import { StoreScopedSearch } from "./StoreScopedSearch";
5
6
  export function StoreHeader({ store, labels = {}, onFollow, className = "", }) {
6
7
  return (_jsxs(Section, { surface: "default", className: `border-b border-gray-200 dark:border-slate-700 ${className}`, children: [store.storeBannerURL && (_jsx(Div, { className: "h-40 md:h-56 overflow-hidden bg-gray-100 dark:bg-slate-800", children: _jsx(Div, { role: "img", "aria-label": `${store.storeName} banner`, className: "h-full w-full bg-center bg-cover", style: { backgroundImage: `url(${store.storeBannerURL})` } }) })), _jsxs(Div, { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4", children: [_jsxs(Div, { className: "flex items-end gap-4", children: [store.storeLogoURL ? (_jsx(Div, { role: "img", "aria-label": store.storeName, className: "-mt-8 h-16 w-16 rounded-xl border-2 border-white dark:border-slate-800 bg-center bg-cover shadow-sm", style: { backgroundImage: `url(${store.storeLogoURL})` } })) : (_jsx(Div, { className: "-mt-8 h-16 w-16 rounded-xl border-2 border-white dark:border-slate-800 bg-orange-100 dark:bg-orange-900/30 flex items-center justify-center text-orange-600 dark:text-orange-400 font-bold text-2xl shadow-sm", children: store.storeName[0]?.toUpperCase() })), _jsxs(Div, { className: "flex-1 min-w-0", children: [_jsxs(Div, { className: "flex flex-wrap items-center gap-2 mb-0.5", children: [_jsx(Heading, { level: 1, className: "text-xl font-bold text-gray-900 dark:text-zinc-100", children: store.storeName }), store.averageRating != null && store.averageRating > 0 && (_jsxs(Span, { className: "inline-flex items-center gap-1 text-sm font-medium text-amber-500", children: ["\u2605 ", store.averageRating.toFixed(1)] }))] }), _jsxs(Row, { className: "gap-3 text-xs text-gray-500 dark:text-zinc-400 mb-0.5", children: [store.category && _jsx(Span, { className: "capitalize", children: store.category }), store.totalProducts != null && store.totalProducts > 0 && (_jsxs(Span, { children: [store.totalProducts, " ", labels.products ?? "products"] })), store.totalReviews != null && store.totalReviews > 0 && (_jsxs(Span, { children: [store.totalReviews, " ", labels.reviews ?? "reviews"] })), store.itemsSold != null && store.itemsSold > 0 && (_jsxs(Span, { children: [store.itemsSold, " ", labels.sold ?? "sold"] }))] }), store.storeDescription && (_jsx(RichText, { html: normalizeRichTextHtml(store.storeDescription), copyableCode: true, className: "mt-0.5" }))] }), _jsxs(Row, { gap: "sm", align: "center", className: "shrink-0", children: [_jsx(ShareButton, { title: store.storeName }), onFollow && (_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => onFollow(store.storeSlug), className: "rounded-lg border border-orange-500 px-4 py-2 text-sm font-medium text-orange-500 hover:bg-orange-50 transition-colors", children: labels.follow ?? "Follow" }))] })] }), store.isVacationMode && (_jsx(Text, { className: "mt-3 rounded-lg bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 px-3 py-2 text-sm text-yellow-700 dark:text-yellow-300", children: store.vacationMessage ??
7
8
  labels.vacationMode ??
8
- "Store is on vacation mode" }))] })] }));
9
+ "Store is on vacation mode" })), _jsx(Div, { className: "mt-3", children: _jsx(StoreScopedSearch, { storeId: store.storeSlug, storeName: store.storeName }) })] })] }));
9
10
  }
@@ -1,3 +1,2 @@
1
- export interface StoreListingsGuideViewProps {
2
- }
1
+ export type StoreListingsGuideViewProps = Record<string, never>;
3
2
  export declare function StoreListingsGuideView(_props: StoreListingsGuideViewProps): import("react/jsx-runtime").JSX.Element;
@@ -1,3 +1,2 @@
1
- export interface StoreOrdersGuideViewProps {
2
- }
1
+ export type StoreOrdersGuideViewProps = Record<string, never>;
3
2
  export declare function StoreOrdersGuideView(_props: StoreOrdersGuideViewProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,16 @@
1
+ interface StoreScopedSearchProps {
2
+ storeId: string;
3
+ storeName: string;
4
+ /** Override placeholder; falls back to "Search {storeName}…". */
5
+ placeholder?: string;
6
+ className?: string;
7
+ }
8
+ /**
9
+ * W1-19 — inline search input scoped to a single store. Submits to
10
+ * `/products?storeId={storeId}&q={query}` so the public product listing
11
+ * filters down to this seller's catalog. Lives alongside `StoreHeader` and
12
+ * is the store-page complement to the global `<Search>` slot rendered in
13
+ * `LayoutShellClient`.
14
+ */
15
+ export declare function StoreScopedSearch({ storeId, storeName, placeholder, className, }: StoreScopedSearchProps): import("react/jsx-runtime").JSX.Element;
16
+ export {};
@@ -0,0 +1,27 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { useRouter } from "next/navigation";
5
+ import { Button, Input, Row } from "../../../ui";
6
+ import { ROUTES } from "../../../next/routing/route-map";
7
+ /**
8
+ * W1-19 — inline search input scoped to a single store. Submits to
9
+ * `/products?storeId={storeId}&q={query}` so the public product listing
10
+ * filters down to this seller's catalog. Lives alongside `StoreHeader` and
11
+ * is the store-page complement to the global `<Search>` slot rendered in
12
+ * `LayoutShellClient`.
13
+ */
14
+ export function StoreScopedSearch({ storeId, storeName, placeholder, className = "", }) {
15
+ const router = useRouter();
16
+ const [value, setValue] = useState("");
17
+ const submit = (e) => {
18
+ e.preventDefault();
19
+ const q = value.trim();
20
+ const base = String(ROUTES.PUBLIC.PRODUCTS);
21
+ const params = new URLSearchParams({ storeId });
22
+ if (q)
23
+ params.set("q", q);
24
+ router.push(`${base}?${params.toString()}`);
25
+ };
26
+ return (_jsx("form", { onSubmit: submit, className: `w-full ${className}`, children: _jsxs(Row, { gap: "sm", align: "center", className: "w-full", children: [_jsx(Input, { type: "search", value: value, onChange: (e) => setValue(e.target.value), placeholder: placeholder ?? `Search ${storeName}…`, "aria-label": `Search ${storeName}`, className: "flex-1" }), _jsx(Button, { type: "submit", variant: "primary", size: "sm", children: "Search" })] }) }));
27
+ }
@@ -1,3 +1,2 @@
1
- export interface StoreSettingsGuideViewProps {
2
- }
1
+ export type StoreSettingsGuideViewProps = Record<string, never>;
3
2
  export declare function StoreSettingsGuideView(_props: StoreSettingsGuideViewProps): import("react/jsx-runtime").JSX.Element;
@@ -4,7 +4,6 @@
4
4
  * Server-only entry point — repositories and API route handlers.
5
5
  */
6
6
  export * from "./actions";
7
- export { StoresRepository } from "./repository/stores.repository";
8
7
  export { StoreRepository, storeRepository, } from "./repository/store.repository";
9
8
  export { GET as storesGET, GET } from "./api/route";
10
9
  export { GET as storeSlugGET } from "./api/[storeSlug]/route";
@@ -4,7 +4,6 @@
4
4
  * Server-only entry point — repositories and API route handlers.
5
5
  */
6
6
  export * from "./actions";
7
- export { StoresRepository } from "./repository/stores.repository";
8
7
  export { StoreRepository, storeRepository, } from "./repository/store.repository";
9
8
  // SB-UNI-A 2026-05-13 — storeAddressRepository deleted. Use addressesRepository
10
9
  // (top-level addresses collection with ownerType:"store").
@@ -23,6 +23,9 @@ export declare const TicketCategoryValues: {
23
23
  readonly REFUND_REQUEST: "refund_request";
24
24
  readonly AUCTION_DISPUTE: "auction_dispute";
25
25
  readonly GENERAL: "general";
26
+ readonly STORE_CHANGE_REQUEST: "store_change_request";
27
+ readonly ORDER_MODIFICATION_REQUEST: "order_modification_request";
28
+ readonly UNBAN_REQUEST: "unban_request";
26
29
  };
27
30
  export type TicketCategory = (typeof TicketCategoryValues)[keyof typeof TicketCategoryValues];
28
31
  export declare const TicketStatusValues: {
@@ -54,6 +57,19 @@ export interface TicketMessage {
54
57
  attachments?: string[];
55
58
  createdAt: Date;
56
59
  }
60
+ /**
61
+ * Subject entities a ticket concerns. Assigned by admin/support agents so a
62
+ * single ticket can reference the buyer, store, order, product, or bid in
63
+ * dispute. Used to render clickable chips in the ticket detail view that link
64
+ * to the relevant admin detail page.
65
+ */
66
+ export interface TicketRelatedParties {
67
+ userId?: string;
68
+ storeId?: string;
69
+ orderId?: string;
70
+ productId?: string;
71
+ bidId?: string;
72
+ }
57
73
  export interface SupportTicketDocument {
58
74
  id: string;
59
75
  userId: string;
@@ -67,6 +83,11 @@ export interface SupportTicketDocument {
67
83
  description: string;
68
84
  /** Linked order ID — required when category === "order_issue". */
69
85
  orderId?: string;
86
+ /**
87
+ * ST-6 — subjects of the ticket. Admin/support assignable. `orderId` is
88
+ * mirrored here for consistency when set via the linked-parties panel.
89
+ */
90
+ relatedParties?: TicketRelatedParties;
70
91
  status: TicketStatus;
71
92
  priority: TicketPriority;
72
93
  /** UID of the assigned employee. */
@@ -86,7 +107,7 @@ export interface SupportTicketDocument {
86
107
  updatedAt: Date;
87
108
  }
88
109
  export type SupportTicketCreateInput = Pick<SupportTicketDocument, "userId" | "userEmail" | "userDisplayName" | "category" | "subject" | "description" | "orderId">;
89
- export type SupportTicketUpdateInput = Partial<Pick<SupportTicketDocument, "status" | "priority" | "assignedTo" | "assignedToName" | "internalNotes" | "resolvedAt" | "closedAt">>;
110
+ export type SupportTicketUpdateInput = Partial<Pick<SupportTicketDocument, "status" | "priority" | "assignedTo" | "assignedToName" | "internalNotes" | "resolvedAt" | "closedAt" | "relatedParties">>;
90
111
  export declare const SUPPORT_TICKET_COLLECTION: "supportTickets";
91
112
  export declare const SUPPORT_TICKET_ID_PREFIX: "ticket-";
92
113
  export declare const SUPPORT_TICKET_INDEXED_FIELDS: readonly ["userId", "status", "category", "priority", "assignedTo", "orderId", "createdAt", "updatedAt"];
@@ -26,6 +26,16 @@ export const TicketCategoryValues = {
26
26
  REFUND_REQUEST: "refund_request",
27
27
  AUCTION_DISPUTE: "auction_dispute",
28
28
  GENERAL: "general",
29
+ // ST-4 — sellers request admin-only field changes on their store
30
+ // (status / capabilities / isVerified) through this category.
31
+ STORE_CHANGE_REQUEST: "store_change_request",
32
+ // ST-3 — buyers/sellers request mutation of order line items
33
+ // (wrong item shipped, partial fulfilment, bundle correction).
34
+ ORDER_MODIFICATION_REQUEST: "order_modification_request",
35
+ // ST-5 — users appeal a soft-ban or hard-ban via this category.
36
+ // Server bypasses the create_support_tickets soft-ban guard and the
37
+ // active-ticket limit so the user always has an appeal channel.
38
+ UNBAN_REQUEST: "unban_request",
29
39
  };
30
40
  export const TicketStatusValues = {
31
41
  OPEN: "open",