@mohasinac/appkit 4.53.0 → 4.53.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 (500) hide show
  1. package/dist/.build-stamp.json +3 -3
  2. package/dist/_internal/client/scaffolds/AppShell.js +1 -1
  3. package/dist/_internal/server/features/auctions/og.d.ts +3 -1
  4. package/dist/_internal/server/features/auctions/og.js +3 -1
  5. package/dist/_internal/server/features/bundles/actions.js +1 -1
  6. package/dist/_internal/server/features/business-documents/download.d.ts +41 -0
  7. package/dist/_internal/server/features/business-documents/download.js +91 -0
  8. package/dist/_internal/server/features/categories/adapters.d.ts +1 -1
  9. package/dist/_internal/server/features/categories/adapters.js +10 -0
  10. package/dist/_internal/server/features/checkout/actions.d.ts +14 -0
  11. package/dist/_internal/server/features/checkout/actions.js +106 -12
  12. package/dist/_internal/server/features/checkout/bundle-expansion.js +17 -0
  13. package/dist/_internal/server/features/checkout/data.d.ts +22 -0
  14. package/dist/_internal/server/features/checkout/group-rule-revalidation.d.ts +34 -0
  15. package/dist/_internal/server/features/checkout/group-rule-revalidation.js +124 -0
  16. package/dist/_internal/server/features/checkout/supplier-identity.d.ts +55 -0
  17. package/dist/_internal/server/features/checkout/supplier-identity.js +81 -0
  18. package/dist/_internal/server/features/classified/metadata.js +1 -1
  19. package/dist/_internal/server/features/classified/og.d.ts +3 -1
  20. package/dist/_internal/server/features/classified/og.js +3 -1
  21. package/dist/_internal/server/features/digital-code/metadata.js +1 -1
  22. package/dist/_internal/server/features/digital-code/og.d.ts +3 -1
  23. package/dist/_internal/server/features/digital-code/og.js +3 -1
  24. package/dist/_internal/server/features/digital-code/pool.d.ts +19 -4
  25. package/dist/_internal/server/features/digital-code/pool.js +19 -4
  26. package/dist/_internal/server/features/live/metadata.js +1 -1
  27. package/dist/_internal/server/features/live/og.d.ts +3 -1
  28. package/dist/_internal/server/features/live/og.js +3 -1
  29. package/dist/_internal/server/features/messages/actions.js +1 -1
  30. package/dist/_internal/server/features/parts/og.js +1 -1
  31. package/dist/_internal/server/features/pre-orders/og.d.ts +3 -1
  32. package/dist/_internal/server/features/pre-orders/og.js +3 -1
  33. package/dist/_internal/server/features/price-index/search.d.ts +18 -0
  34. package/dist/_internal/server/features/price-index/search.js +47 -7
  35. package/dist/_internal/server/features/prize-draws/og.d.ts +3 -1
  36. package/dist/_internal/server/features/prize-draws/og.js +3 -1
  37. package/dist/_internal/server/features/products/group-members.d.ts +26 -0
  38. package/dist/_internal/server/features/products/group-members.js +7 -1
  39. package/dist/_internal/server/features/products/og.d.ts +3 -1
  40. package/dist/_internal/server/features/products/og.js +3 -1
  41. package/dist/_internal/server/features/search/scoped-sources.d.ts +26 -0
  42. package/dist/_internal/server/features/search/scoped-sources.js +252 -0
  43. package/dist/_internal/server/features/search/search-everything.d.ts +57 -0
  44. package/dist/_internal/server/features/search/search-everything.js +70 -20
  45. package/dist/_internal/server/features/seo/sitemap.js +6 -0
  46. package/dist/_internal/server/features/shared/listing-adapters.js +4 -2
  47. package/dist/_internal/server/features/sticker-trace/adapters.d.ts +11 -0
  48. package/dist/_internal/server/features/sticker-trace/adapters.js +1 -0
  49. package/dist/_internal/server/features/sticker-trace/promote-to-listings.d.ts +26 -0
  50. package/dist/_internal/server/features/sticker-trace/promote-to-listings.js +264 -0
  51. package/dist/_internal/server/features/sticker-trace/sheet-actions.d.ts +3 -1
  52. package/dist/_internal/server/features/sticker-trace/sheet-actions.js +32 -0
  53. package/dist/_internal/server/features/sticker-trace/storage.d.ts +20 -1
  54. package/dist/_internal/server/features/sticker-trace/storage.js +20 -1
  55. package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
  56. package/dist/_internal/server/features/stores/adapters.js +16 -0
  57. package/dist/_internal/server/features/stores/index.d.ts +1 -0
  58. package/dist/_internal/server/features/stores/index.js +1 -0
  59. package/dist/_internal/server/features/stores/tabs.d.ts +25 -0
  60. package/dist/_internal/server/features/stores/tabs.js +122 -0
  61. package/dist/_internal/shared/checkout/rules/_defaults.js +0 -2
  62. package/dist/_internal/shared/checkout/rules/_limits.d.ts +14 -1
  63. package/dist/_internal/shared/checkout/rules/_limits.js +14 -1
  64. package/dist/_internal/shared/checkout/rules/_registry.js +2 -0
  65. package/dist/_internal/shared/checkout/rules/auction.rule.js +9 -1
  66. package/dist/_internal/shared/checkout/rules/bundle.rule.js +13 -0
  67. package/dist/_internal/shared/checkout/rules/index.d.ts +2 -0
  68. package/dist/_internal/shared/checkout/rules/index.js +9 -0
  69. package/dist/_internal/shared/checkout/rules/offer.rule.js +0 -1
  70. package/dist/_internal/shared/checkout/rules/payment-gate.d.ts +26 -0
  71. package/dist/_internal/shared/checkout/rules/payment-gate.js +133 -0
  72. package/dist/_internal/shared/checkout/rules/prize-draw.rule.js +29 -8
  73. package/dist/_internal/shared/checkout/rules/spares.rule.d.ts +16 -0
  74. package/dist/_internal/shared/checkout/rules/spares.rule.js +5 -0
  75. package/dist/_internal/shared/checkout/rules/types.d.ts +26 -2
  76. package/dist/_internal/shared/config/schema.d.ts +122 -0
  77. package/dist/_internal/shared/features/cart/schema.js +3 -2
  78. package/dist/_internal/shared/features/products/group-rules.d.ts +75 -0
  79. package/dist/_internal/shared/features/products/group-rules.js +142 -0
  80. package/dist/_internal/shared/listing-types/_registry.d.ts +24 -0
  81. package/dist/_internal/shared/listing-types/_registry.js +39 -1
  82. package/dist/_internal/shared/listing-types/art/config.d.ts +1 -0
  83. package/dist/_internal/shared/listing-types/art/config.js +2 -0
  84. package/dist/_internal/shared/listing-types/auction/config.d.ts +1 -0
  85. package/dist/_internal/shared/listing-types/auction/config.js +2 -0
  86. package/dist/_internal/shared/listing-types/availability.js +48 -0
  87. package/dist/_internal/shared/listing-types/capabilities.js +19 -0
  88. package/dist/_internal/shared/listing-types/classified/config.d.ts +1 -0
  89. package/dist/_internal/shared/listing-types/classified/config.js +2 -0
  90. package/dist/_internal/shared/listing-types/digital-code/config.d.ts +1 -0
  91. package/dist/_internal/shared/listing-types/digital-code/config.js +2 -0
  92. package/dist/_internal/shared/listing-types/feature-flags.js +1 -0
  93. package/dist/_internal/shared/listing-types/live/config.d.ts +1 -0
  94. package/dist/_internal/shared/listing-types/live/config.js +2 -0
  95. package/dist/_internal/shared/listing-types/pre-order/config.d.ts +1 -0
  96. package/dist/_internal/shared/listing-types/pre-order/config.js +2 -0
  97. package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +1 -0
  98. package/dist/_internal/shared/listing-types/prize-draw/config.js +2 -0
  99. package/dist/_internal/shared/listing-types/spares/config.d.ts +74 -0
  100. package/dist/_internal/shared/listing-types/spares/config.js +60 -0
  101. package/dist/_internal/shared/listing-types/spares/ctas.d.ts +1 -0
  102. package/dist/_internal/shared/listing-types/spares/ctas.js +4 -0
  103. package/dist/_internal/shared/listing-types/spares/og.js +1 -0
  104. package/dist/_internal/shared/listing-types/spares/schema.d.ts +2 -0
  105. package/dist/_internal/shared/listing-types/spares/schema.js +3 -0
  106. package/dist/_internal/shared/listing-types/spares/seed-factory.d.ts +1 -0
  107. package/dist/_internal/shared/listing-types/spares/seed-factory.js +1 -0
  108. package/dist/_internal/shared/listing-types/standard/config.d.ts +1 -0
  109. package/dist/_internal/shared/listing-types/standard/config.js +2 -0
  110. package/dist/_internal/shared/listing-types/stickers/config.d.ts +1 -0
  111. package/dist/_internal/shared/listing-types/stickers/config.js +2 -0
  112. package/dist/_internal/shared/search/match.d.ts +11 -0
  113. package/dist/_internal/shared/search/match.js +2 -1
  114. package/dist/_internal/shared/search/to-groups.d.ts +52 -0
  115. package/dist/_internal/shared/search/to-groups.js +141 -0
  116. package/dist/client.d.ts +8 -2
  117. package/dist/client.js +4 -1
  118. package/dist/constants/api-endpoints.d.ts +39 -15
  119. package/dist/constants/api-endpoints.js +28 -5
  120. package/dist/constants/cache-invalidation.js +3 -1
  121. package/dist/constants/field-names.d.ts +6 -0
  122. package/dist/constants/field-names.js +6 -0
  123. package/dist/features/about/components/PolicyPageView.d.ts +22 -2
  124. package/dist/features/about/components/PolicyPageView.js +14 -2
  125. package/dist/features/about/components/PublicProfileView.js +2 -1
  126. package/dist/features/about/components/ShippingPolicyView.js +42 -2
  127. package/dist/features/account/components/NotificationBell.js +1 -1
  128. package/dist/features/account/hooks/useProfileStats.js +5 -1
  129. package/dist/features/addresses/repository/addresses.repository.d.ts +16 -0
  130. package/dist/features/addresses/repository/addresses.repository.js +21 -0
  131. package/dist/features/admin/actions/admin-actions.js +16 -1
  132. package/dist/features/admin/components/AdminCategoryEditorView.js +19 -2
  133. package/dist/features/admin/components/AdminNavigationView.js +1 -1
  134. package/dist/features/admin/components/AdminPageHeader.js +1 -1
  135. package/dist/features/admin/components/AdminProductEditorView.js +17 -2
  136. package/dist/features/admin/components/AdminSidebar.js +1 -1
  137. package/dist/features/admin/components/AdminSiteSettingsView.js +39 -8
  138. package/dist/features/admin/components/AdminSparesView.d.ts +12 -0
  139. package/dist/features/admin/components/AdminSparesView.js +30 -0
  140. package/dist/features/admin/components/AdminUsersView.js +9 -7
  141. package/dist/features/admin/components/index.d.ts +2 -0
  142. package/dist/features/admin/components/index.js +1 -0
  143. package/dist/features/admin/components/sections/adminSectionsTypes.js +7 -0
  144. package/dist/features/admin/constants/filter-tabs.d.ts +3 -0
  145. package/dist/features/admin/constants/filter-tabs.js +1 -0
  146. package/dist/features/admin/schemas/firestore.d.ts +26 -2
  147. package/dist/features/auctions/components/AuctionDetailPageView.js +4 -11
  148. package/dist/features/auth/repository/user.repository.d.ts +13 -0
  149. package/dist/features/auth/repository/user.repository.js +28 -0
  150. package/dist/features/auth/schemas/firestore.d.ts +2 -0
  151. package/dist/features/auth/schemas/firestore.js +2 -0
  152. package/dist/features/business-documents/repository/business-documents.repository.d.ts +58 -0
  153. package/dist/features/business-documents/repository/business-documents.repository.js +54 -0
  154. package/dist/features/business-documents/schemas/firestore.d.ts +105 -0
  155. package/dist/features/business-documents/schemas/firestore.js +75 -0
  156. package/dist/features/cart/actions/cart-actions.js +83 -6
  157. package/dist/features/cart/repository/cart.repository.js +32 -4
  158. package/dist/features/cart/schemas/firestore.d.ts +20 -0
  159. package/dist/features/cart/schemas/index.d.ts +2 -2
  160. package/dist/features/catalogue/components/PublicCatalogueItemDetailView.js +1 -1
  161. package/dist/features/categories/api/[id]/price-guidance/route.d.ts +42 -0
  162. package/dist/features/categories/api/[id]/price-guidance/route.js +113 -0
  163. package/dist/features/categories/components/BrandDetailPageView.js +19 -3
  164. package/dist/features/categories/components/BrandDetailTabs.js +10 -0
  165. package/dist/features/categories/components/CategoriesIndexListing.js +23 -8
  166. package/dist/features/categories/components/CategoryDetailPageView.js +141 -14
  167. package/dist/features/categories/components/CategoryDetailTabs.js +12 -0
  168. package/dist/features/categories/components/CategoryGrid.js +10 -1
  169. package/dist/features/categories/components/PriceGuidanceHint.d.ts +29 -0
  170. package/dist/features/categories/components/PriceGuidanceHint.js +61 -0
  171. package/dist/features/categories/components/SubcategoryCardRow.d.ts +27 -0
  172. package/dist/features/categories/components/SubcategoryCardRow.js +98 -0
  173. package/dist/features/categories/constants/category-tabs.d.ts +20 -25
  174. package/dist/features/categories/constants/category-tabs.js +22 -39
  175. package/dist/features/categories/repository/categories.repository.d.ts +12 -0
  176. package/dist/features/categories/repository/categories.repository.js +20 -0
  177. package/dist/features/categories/schemas/firestore.d.ts +22 -1
  178. package/dist/features/categories/schemas/firestore.js +10 -0
  179. package/dist/features/categories/schemas/index.d.ts +6 -0
  180. package/dist/features/categories/schemas/index.js +2 -0
  181. package/dist/features/categories/types/index.d.ts +8 -0
  182. package/dist/features/categories/utils/taxonomy-visual.d.ts +16 -3
  183. package/dist/features/categories/utils/taxonomy-visual.js +26 -10
  184. package/dist/features/classified/components/ClassifiedDetailPageView.js +4 -9
  185. package/dist/features/contact/components/ContactPageView.d.ts +33 -1
  186. package/dist/features/contact/components/ContactPageView.js +58 -28
  187. package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +4 -9
  188. package/dist/features/grouped/components/GroupedListingDetailView.js +9 -1
  189. package/dist/features/grouped/schemas/firestore.d.ts +5 -0
  190. package/dist/features/homepage/actions/homepage-section-actions.d.ts +3 -3
  191. package/dist/features/homepage/components/CollectionCardsSection.d.ts +28 -6
  192. package/dist/features/homepage/components/CollectionCardsSection.js +43 -8
  193. package/dist/features/homepage/components/HowItWorksSection.d.ts +23 -6
  194. package/dist/features/homepage/components/HowItWorksSection.js +4 -4
  195. package/dist/features/homepage/components/PromoGrid.d.ts +31 -2
  196. package/dist/features/homepage/components/PromoGrid.js +12 -3
  197. package/dist/features/homepage/components/TestimonialsCarousel.d.ts +34 -2
  198. package/dist/features/homepage/components/TestimonialsCarousel.js +1 -1
  199. package/dist/features/homepage/components/index.d.ts +0 -20
  200. package/dist/features/homepage/components/index.js +0 -11
  201. package/dist/features/homepage/index.d.ts +0 -2
  202. package/dist/features/homepage/index.js +0 -2
  203. package/dist/features/homepage/lib/section-renderer.d.ts +9 -0
  204. package/dist/features/homepage/lib/section-renderer.js +202 -58
  205. package/dist/features/homepage/repository/homepage-sections.repository.d.ts +35 -3
  206. package/dist/features/homepage/repository/homepage-sections.repository.js +58 -8
  207. package/dist/features/homepage/schemas/firestore.d.ts +106 -3
  208. package/dist/features/homepage/schemas/firestore.js +32 -2
  209. package/dist/features/homepage/schemas/index.d.ts +36 -7
  210. package/dist/features/homepage/schemas/index.js +39 -27
  211. package/dist/features/homepage/server.d.ts +0 -3
  212. package/dist/features/homepage/server.js +0 -3
  213. package/dist/features/homepage/types/index.d.ts +0 -47
  214. package/dist/features/homepage/types/index.js +49 -0
  215. package/dist/features/layout/AppLayoutShell.js +1 -1
  216. package/dist/features/layout/BottomNavItem.js +1 -1
  217. package/dist/features/layout/BottomSheet.js +1 -1
  218. package/dist/features/layout/TitleBarLayout.js +1 -1
  219. package/dist/features/live/components/LiveItemDetailPageView.js +4 -9
  220. package/dist/features/media/hooks/useMedia.js +17 -0
  221. package/dist/features/media/repository/media-assets.repository.d.ts +46 -0
  222. package/dist/features/media/repository/media-assets.repository.js +31 -0
  223. package/dist/features/media/trust-signals.d.ts +85 -0
  224. package/dist/features/media/trust-signals.js +126 -0
  225. package/dist/features/parts/components/PartDetailPageView.d.ts +14 -1
  226. package/dist/features/parts/components/PartDetailPageView.js +2 -2
  227. package/dist/features/parts/components/PartsIndexPageView.d.ts +11 -2
  228. package/dist/features/parts/components/PartsIndexPageView.js +2 -2
  229. package/dist/features/parts/components/PartsSearchBox.d.ts +9 -0
  230. package/dist/features/parts/components/PartsSearchBox.js +57 -0
  231. package/dist/features/parts/schemas/firestore.d.ts +149 -3
  232. package/dist/features/parts/schemas/firestore.js +184 -0
  233. package/dist/features/payments/repository/payout.repository.d.ts +15 -0
  234. package/dist/features/payments/repository/payout.repository.js +21 -0
  235. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +4 -11
  236. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +1 -1
  237. package/dist/features/price-index/components/PriceIndexToolView.d.ts +3 -1
  238. package/dist/features/price-index/components/PriceIndexToolView.js +92 -13
  239. package/dist/features/products/components/CompareOverlay.d.ts +18 -1
  240. package/dist/features/products/components/CompareOverlay.js +21 -2
  241. package/dist/features/products/components/CustomSectionTabContent.d.ts +31 -0
  242. package/dist/features/products/components/CustomSectionTabContent.js +29 -3
  243. package/dist/features/products/components/GroupMemberPicker.d.ts +19 -1
  244. package/dist/features/products/components/GroupMemberPicker.js +46 -8
  245. package/dist/features/products/components/GroupSettingsPanel.d.ts +11 -1
  246. package/dist/features/products/components/GroupSettingsPanel.js +91 -3
  247. package/dist/features/products/components/PrizeDrawDetailPageView.js +1 -1
  248. package/dist/features/products/components/PrizeDrawEntryActions.d.ts +15 -1
  249. package/dist/features/products/components/PrizeDrawEntryActions.js +70 -8
  250. package/dist/features/products/components/ProductDetailPageView.js +74 -15
  251. package/dist/features/products/components/ProductForm.d.ts +13 -1
  252. package/dist/features/products/components/ProductForm.js +16 -2
  253. package/dist/features/products/components/ProductsIndexListing.d.ts +16 -1
  254. package/dist/features/products/components/ProductsIndexListing.js +3 -3
  255. package/dist/features/products/components/ShowGroupSection.js +15 -2
  256. package/dist/features/products/components/SparesListView.d.ts +7 -0
  257. package/dist/features/products/components/SparesListView.js +39 -0
  258. package/dist/features/products/constants/action-defs.d.ts +1 -0
  259. package/dist/features/products/constants/action-defs.js +1 -0
  260. package/dist/features/products/repository/products.repository.d.ts +98 -0
  261. package/dist/features/products/repository/products.repository.js +235 -17
  262. package/dist/features/products/schemas/firestore.d.ts +97 -4
  263. package/dist/features/products/schemas/firestore.js +104 -0
  264. package/dist/features/products/schemas/index.d.ts +10 -19
  265. package/dist/features/products/schemas/index.js +23 -6
  266. package/dist/features/products/types/index.d.ts +45 -1
  267. package/dist/features/products/utils/group-member-image.d.ts +39 -0
  268. package/dist/features/products/utils/group-member-image.js +3 -0
  269. package/dist/features/products/utils/listing-badge-variant.js +4 -0
  270. package/dist/features/reviews/components/ReviewsList.js +1 -1
  271. package/dist/features/scams/components/ScamProfileView.js +1 -1
  272. package/dist/features/search/components/EntityTypeahead.d.ts +44 -0
  273. package/dist/features/search/components/EntityTypeahead.js +92 -0
  274. package/dist/features/search/components/Search.d.ts +12 -1
  275. package/dist/features/search/components/Search.js +47 -3
  276. package/dist/features/search/components/SearchFacetRail.d.ts +11 -0
  277. package/dist/features/search/components/SearchFacetRail.js +92 -0
  278. package/dist/features/search/components/SearchResultsClient.d.ts +33 -0
  279. package/dist/features/search/components/SearchResultsClient.js +103 -0
  280. package/dist/features/search/components/SearchResultsPageView.d.ts +15 -1
  281. package/dist/features/search/components/SearchResultsPageView.js +2 -2
  282. package/dist/features/search/components/index.d.ts +0 -6
  283. package/dist/features/search/components/index.js +0 -3
  284. package/dist/features/search/hooks/useNavSuggestions.d.ts +13 -0
  285. package/dist/features/search/hooks/useScopedSearch.d.ts +34 -0
  286. package/dist/features/search/hooks/useScopedSearch.js +114 -0
  287. package/dist/features/search/hooks/useSiteSearch.d.ts +26 -0
  288. package/dist/features/search/hooks/useSiteSearch.js +149 -0
  289. package/dist/features/search/index.d.ts +0 -4
  290. package/dist/features/search/index.js +0 -4
  291. package/dist/features/search/manifest.d.ts +12 -0
  292. package/dist/features/search/manifest.js +17 -2
  293. package/dist/features/search/server.d.ts +0 -3
  294. package/dist/features/search/server.js +0 -3
  295. package/dist/features/seller/components/SellerListingTypeView.d.ts +1 -1
  296. package/dist/features/seller/components/SellerListingTypeView.js +20 -0
  297. package/dist/features/seller/components/SellerPayoutSettingsView.js +35 -14
  298. package/dist/features/seller/components/SellerProductShell.d.ts +1 -1
  299. package/dist/features/seller/components/SellerProductShell.js +2 -1
  300. package/dist/features/seller/components/SellerSidebar.js +1 -1
  301. package/dist/features/seller/components/SellerSparesView.d.ts +17 -0
  302. package/dist/features/seller/components/SellerSparesView.js +6 -0
  303. package/dist/features/seller/components/index.d.ts +2 -0
  304. package/dist/features/seller/components/index.js +1 -0
  305. package/dist/features/shell/CommandPalette.js +1 -1
  306. package/dist/features/sticker-trace/schemas/firestore.d.ts +19 -0
  307. package/dist/features/stores/components/StoreDetailLayoutView.d.ts +1 -1
  308. package/dist/features/stores/components/StoreDetailLayoutView.js +7 -82
  309. package/dist/features/stores/components/StoreHeader.js +1 -2
  310. package/dist/features/stores/components/StoreSparesPageView.d.ts +27 -0
  311. package/dist/features/stores/components/StoreSparesPageView.js +48 -0
  312. package/dist/features/stores/schemas/firestore.d.ts +19 -0
  313. package/dist/features/tester/seed-data/authored/buying__spares-and-groups.d.ts +2 -0
  314. package/dist/features/tester/seed-data/authored/buying__spares-and-groups.js +96 -0
  315. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.d.ts +2 -0
  316. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.js +280 -45
  317. package/dist/features/tester/seed-data/authored/content-discovery__category-tabs-franchise-bundles.js +54 -32
  318. package/dist/features/tester/seed-data/authored/content-discovery__parts-database.js +3 -2
  319. package/dist/features/tester/seed-data/authored/content-discovery__price-index-and-compare.d.ts +2 -0
  320. package/dist/features/tester/seed-data/authored/content-discovery__price-index-and-compare.js +73 -0
  321. package/dist/features/tester/seed-data/authored/content-discovery__site-wide-index.d.ts +2 -0
  322. package/dist/features/tester/seed-data/authored/content-discovery__site-wide-index.js +340 -0
  323. package/dist/features/tester/seed-data/authored/index.js +16 -0
  324. package/dist/features/tester/seed-data/authored/search-and-nav__header-search.d.ts +1 -0
  325. package/dist/features/tester/seed-data/authored/search-and-nav__header-search.js +57 -0
  326. package/dist/features/tester/seed-data/authored/selling__spares-and-group-editing.d.ts +2 -0
  327. package/dist/features/tester/seed-data/authored/selling__spares-and-group-editing.js +77 -0
  328. package/dist/features/tester/seed-data/authored/tools__sticker-promote-to-listings.d.ts +2 -0
  329. package/dist/features/tester/seed-data/authored/tools__sticker-promote-to-listings.js +58 -0
  330. package/dist/features/tester/seed-data/authored/tools__sticker-tracer.js +5 -4
  331. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +372 -18
  332. package/dist/index.d.ts +17 -57
  333. package/dist/index.js +35 -96
  334. package/dist/next/routing/route-map.d.ts +42 -1
  335. package/dist/next/routing/route-map.js +45 -0
  336. package/dist/providers/db-firebase/base.repository.d.ts +22 -0
  337. package/dist/providers/db-firebase/base.repository.js +36 -0
  338. package/dist/schemas/registry.d.ts +15 -6
  339. package/dist/security/blind-index-tokens.d.ts +54 -0
  340. package/dist/security/blind-index-tokens.js +152 -0
  341. package/dist/security/index.d.ts +1 -1
  342. package/dist/security/index.js +1 -1
  343. package/dist/security/settings-encryption.d.ts +35 -0
  344. package/dist/security/settings-encryption.js +91 -0
  345. package/dist/seed/_helpers/brand-rows.js +38 -14
  346. package/dist/seed/_helpers/category-forest.js +73 -7
  347. package/dist/seed/_helpers/category-images-generated.d.ts +25 -6
  348. package/dist/seed/_helpers/category-images-generated.js +81 -6
  349. package/dist/seed/_helpers/category-models.d.ts +1 -1
  350. package/dist/seed/_helpers/category-models.js +7 -1
  351. package/dist/seed/_helpers/category-parts-glossary-map.js +8 -0
  352. package/dist/seed/_helpers/category-parts.d.ts +1 -1
  353. package/dist/seed/_helpers/category-parts.js +50 -2
  354. package/dist/seed/_helpers/character-features.d.ts +1 -1
  355. package/dist/seed/_helpers/character-features.js +2 -1
  356. package/dist/seed/_helpers/franchise-rows.js +10 -2
  357. package/dist/seed/_helpers/media.d.ts +47 -0
  358. package/dist/seed/_helpers/media.js +34 -0
  359. package/dist/seed/authenticity-knowledge-seed-data.d.ts +49 -5
  360. package/dist/seed/authenticity-knowledge-seed-data.js +10001 -549
  361. package/dist/seed/categories-seed-data.js +124 -20
  362. package/dist/seed/grouped-listings-seed-data.js +16 -0
  363. package/dist/seed/homepage-sections-seed-data.js +94 -5
  364. package/dist/seed/index.d.ts +2 -3
  365. package/dist/seed/index.js +2 -2
  366. package/dist/seed/manifest.js +3 -0
  367. package/dist/seed/media-assets-seed-data.d.ts +1 -1
  368. package/dist/seed/media-assets-seed-data.js +746 -196
  369. package/dist/seed/model-composition-seed-data.js +122 -6
  370. package/dist/seed/part-glossary-seed-data.d.ts +1 -1
  371. package/dist/seed/part-glossary-seed-data.js +37219 -463
  372. package/dist/seed/products-art-seed-data.js +7 -18
  373. package/dist/seed/products-auctions-seed-data.js +56 -47
  374. package/dist/seed/products-beyblade-x-seed-data.d.ts +2 -0
  375. package/dist/seed/products-beyblade-x-seed-data.js +441 -0
  376. package/dist/seed/products-catalogue-seed-data.d.ts +5 -5
  377. package/dist/seed/products-catalogue-seed-data.js +1500 -1240
  378. package/dist/seed/products-classifieds-seed-data.js +9 -27
  379. package/dist/seed/products-digital-codes-seed-data.js +9 -18
  380. package/dist/seed/products-live-items-seed-data.js +5 -13
  381. package/dist/seed/products-preorders-seed-data.js +67 -33
  382. package/dist/seed/products-prize-draws-seed-data.js +8 -17
  383. package/dist/seed/products-spares-seed-data.d.ts +2 -0
  384. package/dist/seed/products-spares-seed-data.js +368 -0
  385. package/dist/seed/products-standard-seed-data.js +39 -126
  386. package/dist/seed/products-stickers-seed-data.js +59 -15
  387. package/dist/seed/site-settings-seed-data.js +8 -0
  388. package/dist/seo/json-ld.d.ts +25 -0
  389. package/dist/seo/json-ld.js +28 -0
  390. package/dist/server-entry.d.ts +3 -1
  391. package/dist/server-entry.js +2 -2
  392. package/dist/server.d.ts +9 -9
  393. package/dist/server.js +27 -25
  394. package/dist/styles.css +202 -1
  395. package/dist/tailwind-input.css +31 -17
  396. package/dist/tailwind-utilities.css +1 -1
  397. package/dist/ui/components/Accordion.js +1 -1
  398. package/dist/ui/components/Breadcrumb.js +1 -1
  399. package/dist/ui/components/DetailPageGallery.js +0 -2
  400. package/dist/ui/components/DetailPageHero.js +0 -1
  401. package/dist/ui/components/DetailPageTabs.js +1 -1
  402. package/dist/ui/components/Divider.js +3 -3
  403. package/dist/ui/components/GatedPrice.js +5 -1
  404. package/dist/ui/components/HorizontalScroller.js +1 -1
  405. package/dist/ui/components/ListingLayout.js +3 -3
  406. package/dist/ui/components/MediaTabs.style.css +81 -0
  407. package/dist/ui/components/Pagination.js +1 -1
  408. package/dist/ui/components/PendingValue.d.ts +45 -0
  409. package/dist/ui/components/PendingValue.js +7 -0
  410. package/dist/ui/components/Radio.style.css +119 -0
  411. package/dist/ui/components/RatingDisplay.js +2 -2
  412. package/dist/ui/components/SettingsSection.js +0 -2
  413. package/dist/ui/components/SiteLogo.js +3 -0
  414. package/dist/ui/components/SiteMark.js +3 -0
  415. package/dist/ui/components/SortDropdown.js +1 -1
  416. package/dist/ui/components/SpecTable.d.ts +58 -0
  417. package/dist/ui/components/SpecTable.js +8 -0
  418. package/dist/ui/components/StarRating.js +1 -3
  419. package/dist/ui/components/SummaryCard.js +1 -1
  420. package/dist/ui/components/index.style.css +1 -0
  421. package/dist/ui/icons/icon-registry.d.ts +1 -0
  422. package/dist/ui/icons/icon-registry.js +9 -1
  423. package/dist/ui/index.d.ts +4 -0
  424. package/dist/ui/index.js +2 -0
  425. package/dist/utils/search-txt-query.d.ts +12 -0
  426. package/dist/utils/search-txt-query.js +12 -0
  427. package/package.json +1 -1
  428. package/scripts/dedupe-peer-deps.mjs +18 -0
  429. package/scripts/seed-cli.mjs +135 -26
  430. package/scripts/verify-css-build.mjs +118 -37
  431. package/dist/_internal/server/features/search/actions.d.ts +0 -7
  432. package/dist/_internal/server/features/search/actions.js +0 -21
  433. package/dist/_internal/server/features/search/data.d.ts +0 -15
  434. package/dist/_internal/server/features/search/data.js +0 -18
  435. package/dist/_internal/server/features/search/index.d.ts +0 -3
  436. package/dist/_internal/server/features/search/index.js +0 -2
  437. package/dist/features/homepage/api/[id]/route.d.ts +0 -23
  438. package/dist/features/homepage/api/[id]/route.js +0 -103
  439. package/dist/features/homepage/api/route.d.ts +0 -14
  440. package/dist/features/homepage/api/route.js +0 -140
  441. package/dist/features/homepage/api/sections/[id]/route.d.ts +0 -26
  442. package/dist/features/homepage/api/sections/[id]/route.js +0 -95
  443. package/dist/features/homepage/api/sections/route.d.ts +0 -13
  444. package/dist/features/homepage/api/sections/route.js +0 -82
  445. package/dist/features/homepage/components/AdvertisementBanner.d.ts +0 -14
  446. package/dist/features/homepage/components/AdvertisementBanner.js +0 -35
  447. package/dist/features/homepage/components/BeforeAfterCard.d.ts +0 -9
  448. package/dist/features/homepage/components/BeforeAfterCard.js +0 -73
  449. package/dist/features/homepage/components/FeaturedResultsSection.d.ts +0 -17
  450. package/dist/features/homepage/components/FeaturedResultsSection.js +0 -17
  451. package/dist/features/homepage/components/HeroBanner.d.ts +0 -7
  452. package/dist/features/homepage/components/HeroBanner.js +0 -43
  453. package/dist/features/homepage/components/HeroSection.d.ts +0 -7
  454. package/dist/features/homepage/components/HeroSection.js +0 -6
  455. package/dist/features/homepage/components/HomepageSkeleton.d.ts +0 -2
  456. package/dist/features/homepage/components/HomepageSkeleton.js +0 -21
  457. package/dist/features/homepage/components/HomepageView.d.ts +0 -25
  458. package/dist/features/homepage/components/HomepageView.js +0 -5
  459. package/dist/features/homepage/components/NewsletterBanner.d.ts +0 -23
  460. package/dist/features/homepage/components/NewsletterBanner.js +0 -37
  461. package/dist/features/homepage/components/SiteFeaturesSection.d.ts +0 -14
  462. package/dist/features/homepage/components/SiteFeaturesSection.js +0 -11
  463. package/dist/features/homepage/components/TrustBadges.d.ts +0 -6
  464. package/dist/features/homepage/components/TrustBadges.js +0 -46
  465. package/dist/features/homepage/components/TrustIndicatorsSection.d.ts +0 -12
  466. package/dist/features/homepage/components/TrustIndicatorsSection.js +0 -11
  467. package/dist/features/homepage/hooks/useHomepage.d.ts +0 -11
  468. package/dist/features/homepage/hooks/useHomepage.js +0 -17
  469. package/dist/features/homepage/hooks/useHomepageSections.d.ts +0 -2
  470. package/dist/features/homepage/hooks/useHomepageSections.js +0 -10
  471. package/dist/features/homepage/repository/homepage.repository.d.ts +0 -11
  472. package/dist/features/homepage/repository/homepage.repository.js +0 -25
  473. package/dist/features/search/actions/index.d.ts +0 -1
  474. package/dist/features/search/actions/index.js +0 -1
  475. package/dist/features/search/actions/search-actions.d.ts +0 -18
  476. package/dist/features/search/actions/search-actions.js +0 -43
  477. package/dist/features/search/api/route.d.ts +0 -22
  478. package/dist/features/search/api/route.js +0 -128
  479. package/dist/features/search/columns/index.d.ts +0 -17
  480. package/dist/features/search/columns/index.js +0 -49
  481. package/dist/features/search/components/SearchFiltersRow.d.ts +0 -22
  482. package/dist/features/search/components/SearchFiltersRow.js +0 -21
  483. package/dist/features/search/components/SearchResultsSection.d.ts +0 -53
  484. package/dist/features/search/components/SearchResultsSection.js +0 -35
  485. package/dist/features/search/components/SearchView.d.ts +0 -27
  486. package/dist/features/search/components/SearchView.js +0 -8
  487. package/dist/features/search/hooks/useSearch.d.ts +0 -21
  488. package/dist/features/search/hooks/useSearch.js +0 -33
  489. package/dist/features/search/repository/search.repository.d.ts +0 -14
  490. package/dist/features/search/repository/search.repository.js +0 -59
  491. package/dist/features/search/schemas/index.d.ts +0 -70
  492. package/dist/features/search/schemas/index.js +0 -36
  493. package/dist/features/search/types/index.d.ts +0 -48
  494. package/dist/features/stores/components/StoreScopedSearch.d.ts +0 -17
  495. package/dist/features/stores/components/StoreScopedSearch.js +0 -27
  496. package/dist/seed/defaults/homepage-sections.d.ts +0 -2
  497. package/dist/seed/defaults/homepage-sections.js +0 -60
  498. package/dist/seed/factories/homepage-section.factory.d.ts +0 -10
  499. package/dist/seed/factories/homepage-section.factory.js +0 -13
  500. /package/dist/{features/search/types/index.js → _internal/shared/listing-types/spares/og.d.ts} +0 -0
@@ -0,0 +1,114 @@
1
+ "use client";
2
+ /*
3
+ * WHY: A signed-in viewer's own records belong in the same box as the public
4
+ * catalogue — but they cost real reads and must not be fetched the way
5
+ * the free tier is.
6
+ * WHAT: Tier 2's client half, plus the merge with Tier 1.
7
+ *
8
+ * ## 🛑 ON SUBMIT, never per keystroke
9
+ *
10
+ * Tier 1 is a local scan and costs nothing, so it runs on every character.
11
+ * This one is a bounded Firestore fan-out — up to ~320 documents for an
12
+ * admin — so it runs when the user commits to a query. A debounced
13
+ * per-keystroke version of this endpoint is how a 50k/day read tier
14
+ * disappears in an afternoon.
15
+ *
16
+ * ## 🛑 A guest issues ZERO requests
17
+ *
18
+ * Gated on `enabled`, which the caller sets from the session. The server
19
+ * refuses too (`auth: true`, and `scopedSourcesFor(null)` is `[]`), but the
20
+ * client gate is what makes "signed out = no authenticated request in the
21
+ * Network panel" true, which is the only form of that claim anyone can
22
+ * verify.
23
+ *
24
+ * @tag domain:search
25
+ * @tag layer:feature
26
+ * @tag pattern:hook
27
+ * @tag access:client
28
+ * @tag consumers:SearchResultsClient
29
+ * @tag sideEffects:network
30
+ */
31
+ import * as React from "react";
32
+ import { apiClient } from "../../../http/index.js";
33
+ import { normalizeError } from "../../../errors/normalize.js";
34
+ import { SEARCH_ENDPOINTS } from "../../../constants/api-endpoints.js";
35
+ /** Matches the server-side gate, so the two cannot disagree about what is worth asking. */
36
+ const MIN_CHARS = 3;
37
+ export function useScopedSearch({ enabled, submittedQuery, }) {
38
+ const [status, setStatus] = React.useState("idle");
39
+ const [groups, setGroups] = React.useState([]);
40
+ React.useEffect(() => {
41
+ const q = submittedQuery.trim();
42
+ if (!enabled || q.length < MIN_CHARS) {
43
+ setStatus("idle");
44
+ setGroups([]);
45
+ return;
46
+ }
47
+ /*
48
+ * An `AbortController` per query, mirroring `useNavSuggestions`. Without
49
+ * it, a slow response to an earlier query can land after a faster
50
+ * response to a later one and overwrite it — the user sees results for
51
+ * something they already moved on from, which looks like the search
52
+ * returning the wrong thing rather than like a race.
53
+ */
54
+ const controller = new AbortController();
55
+ setStatus("loading");
56
+ apiClient
57
+ .get(SEARCH_ENDPOINTS.SCOPED(q), { signal: controller.signal })
58
+ .then((res) => {
59
+ if (controller.signal.aborted)
60
+ return;
61
+ setGroups(res?.data?.groups ?? []);
62
+ setStatus("ready");
63
+ })
64
+ .catch((err) => {
65
+ if (controller.signal.aborted)
66
+ return;
67
+ const e = normalizeError(err);
68
+ /*
69
+ * `failed`, and the CALLER must say so out loud.
70
+ * `searchEverything`'s own header records that a degraded source "is
71
+ * indistinguishable from 'nothing matched'" — and on a page where
72
+ * the public half rendered fine, silence tells a seller their draft
73
+ * does not exist.
74
+ */
75
+ void e;
76
+ setGroups([]);
77
+ setStatus("failed");
78
+ });
79
+ return () => controller.abort();
80
+ }, [enabled, submittedQuery]);
81
+ return { status, groups };
82
+ }
83
+ /**
84
+ * Merge the two tiers.
85
+ *
86
+ * ## 🛑 Dedupe by DESTINATION, and local wins
87
+ *
88
+ * The tiers are NOT disjoint: a seller's published listing is in the public
89
+ * artifact AND in `my-listings`. Showing both is a duplicate-results bug;
90
+ * dropping the public one would lose the row a buyer would see.
91
+ *
92
+ * Local wins, so what survives in the scoped group is precisely the rows the
93
+ * artifact does not have — a seller's DRAFTS. Labelling that group "Your
94
+ * listings (incl. drafts)" is what makes the dedupe legible rather than
95
+ * mysterious.
96
+ *
97
+ * 🛑 The key is the HREF, not `${typeKey}:${id}`. The artifact keys products
98
+ * by SLUG and Firestore by document id, so a composite key would never
99
+ * collide and the dedupe would silently do nothing — the failure mode being
100
+ * a page that looks fine and shows everything twice. Both tiers already
101
+ * agree on where a row goes, which is the only identity they share.
102
+ */
103
+ export function mergeSearchTiers(local, scoped) {
104
+ const seen = new Set();
105
+ for (const g of local)
106
+ for (const h of g.hits)
107
+ seen.add(h.href);
108
+ const deduped = scoped
109
+ .map((g) => ({ ...g, hits: g.hits.filter((h) => !seen.has(h.href)) }))
110
+ // A scoped group that is now empty is dropped entirely rather than
111
+ // rendered as a heading over nothing, which reads as a broken section.
112
+ .filter((g) => g.hits.length > 0);
113
+ return [...local, ...deduped];
114
+ }
@@ -0,0 +1,26 @@
1
+ import { type FacetCount } from "../../../_internal/shared/search/to-groups";
2
+ import { type SearchIndexStatus } from "./useSearchIndex";
3
+ import type { SearchEverythingResult } from "../../../_internal/server/features/search/search-everything";
4
+ import type { NavSuggestionRecord } from "./useNavSuggestions";
5
+ export interface UseSiteSearchOptions {
6
+ /** Flip true on focus or first keypress. Gates the artifact fetch. */
7
+ active: boolean;
8
+ /** `siteSettings.search?.indexEnabled` — read as `!== false`. */
9
+ indexEnabled?: boolean;
10
+ /** Restrict to these index type keys. Absent means every type. */
11
+ types?: readonly string[];
12
+ /** Require every one of these `k:v` pairs. The facet rail's selection. */
13
+ facets?: readonly string[];
14
+ /** `typeKey` -> heading. See `ToGroupsOptions.label`. */
15
+ label: (typeKey: string) => string;
16
+ }
17
+ export interface UseSiteSearchResult {
18
+ readonly status: SearchIndexStatus;
19
+ /** Null until the index is ready; never a fabricated empty result. */
20
+ readonly result: SearchEverythingResult | null;
21
+ readonly suggestions: readonly NavSuggestionRecord[];
22
+ readonly facets: readonly FacetCount[];
23
+ /** The index build this answered from, for a "results as of" line. */
24
+ readonly builtAt: string | null;
25
+ }
26
+ export declare function useSiteSearch(query: string, { active, indexEnabled, types, facets, label }: UseSiteSearchOptions): UseSiteSearchResult;
@@ -0,0 +1,149 @@
1
+ "use client";
2
+ /*
3
+ * WHY: One query, one matcher, two surfaces — the header dropdown and
4
+ * `/search` must not grow separate notions of what matches.
5
+ * WHAT: The client search hook. Runs the browser matcher over the loaded
6
+ * artifact and returns BOTH shapes: grouped results for the page and
7
+ * flat suggestion rows for the typeahead.
8
+ *
9
+ * ## 🛑 Synchronous per keystroke, and no debounce
10
+ *
11
+ * There is nothing to debounce — a debounce exists to avoid spending a
12
+ * network round trip per character, and this spends none. `searchIndex` is a
13
+ * linear scan over ~3,700 prepared records, measured sub-millisecond by
14
+ * `verify-search-local.mjs`. Adding a 250 ms debounce here would make the box
15
+ * feel SLOWER than the thing it replaced while costing nothing less.
16
+ *
17
+ * The one thing that is async is loading the artifact, once, and `active`
18
+ * gates that (see `useSearchIndex`).
19
+ *
20
+ * ## 🛑 No minimum query length either
21
+ *
22
+ * `useNavSuggestions` gates at 3 characters because each query is a real
23
+ * Firestore round trip and below that the result is dominated by whatever
24
+ * sorts first. Neither clause holds here: a one-character query costs the
25
+ * same nothing, and the matcher ranks rather than truncates. Typing "d" and
26
+ * seeing something is the behaviour a local index is FOR.
27
+ *
28
+ * ## It returns a result even when the index is not in play
29
+ *
30
+ * `status` distinguishes `idle` / `loading` / `ready` / `failed` / `disabled`,
31
+ * and the last two mean *the caller should fall back*, not *show nothing*.
32
+ * A caller that renders an empty state on `loading` is saying "nothing
33
+ * matched" about a question that has not been asked yet.
34
+ *
35
+ * @tag domain:search
36
+ * @tag layer:feature
37
+ * @tag pattern:hook
38
+ * @tag access:client
39
+ * @tag consumers:Search,SearchResultsClient
40
+ * @tag sideEffects:none
41
+ */
42
+ import * as React from "react";
43
+ import { searchIndex } from "../../../_internal/shared/search/match.js";
44
+ import { countFacets, moreHrefResolver, toSearchResult, } from "../../../_internal/shared/search/to-groups.js";
45
+ import { parseSearchTxtQuery } from "../../../utils/search-txt.js";
46
+ import { useSearchIndex } from "./useSearchIndex.js";
47
+ /**
48
+ * How many hits the matcher is asked for.
49
+ *
50
+ * Generous because grouping happens AFTER: a cap of 20 on a query matching
51
+ * 400 products would starve every other group, since the list is
52
+ * score-ordered and products would fill it. 200 keeps the long tail of types
53
+ * reachable while staying trivial to sort.
54
+ */
55
+ const MATCH_LIMIT = 200;
56
+ /**
57
+ * `typeKey` -> the five values the header dropdown's icon and badge maps
58
+ * understand.
59
+ *
60
+ * 🛑 A MAPPING rather than a widening of `NavSuggestionRecord["type"]`.
61
+ * That union is public API and is switched on by the dropdown's
62
+ * `DEFAULT_TYPE_ICONS` / `DEFAULT_TYPE_BADGES`; widening it to `string` would
63
+ * compile everywhere and silently render unstyled rows for the 16 index types
64
+ * those maps have never heard of (Root Cause #20). The real key travels
65
+ * alongside, in `typeKey`, for anything that wants it.
66
+ */
67
+ function suggestionTypeFor(typeKey) {
68
+ switch (typeKey) {
69
+ case "blog":
70
+ return "blog";
71
+ case "event":
72
+ return "event";
73
+ case "category":
74
+ case "brand":
75
+ case "franchise":
76
+ case "bundle":
77
+ case "model":
78
+ case "part":
79
+ return "category";
80
+ case "store":
81
+ case "faq":
82
+ case "review":
83
+ case "scammer":
84
+ case "coupon":
85
+ case "group":
86
+ return "page";
87
+ default:
88
+ // Every listing type — product, auction, pre-order, … — plus anything
89
+ // added to the index later. A listing is the commonest row and the
90
+ // product icon is the right default for an unknown one.
91
+ return "product";
92
+ }
93
+ }
94
+ export function useSiteSearch(query, { active, indexEnabled, types, facets, label }) {
95
+ const { status, index } = useSearchIndex({ active, indexEnabled });
96
+ /*
97
+ * 🛑 `types` and `facets` are arrays, so a caller passing a literal creates
98
+ * a new identity every render and would re-run the scan on every keystroke
99
+ * of an UNCHANGED filter. Keying the memo on the joined strings makes the
100
+ * dependency structural rather than referential.
101
+ */
102
+ const typeKey = types ? types.join(",") : "";
103
+ const facetKey = facets ? facets.join(",") : "";
104
+ return React.useMemo(() => {
105
+ if (!index) {
106
+ return { status, result: null, suggestions: [], facets: [], builtAt: null };
107
+ }
108
+ const q = query.trim();
109
+ if (!q) {
110
+ return {
111
+ status,
112
+ result: null,
113
+ suggestions: [],
114
+ facets: [],
115
+ builtAt: index.builtAt,
116
+ };
117
+ }
118
+ const hits = searchIndex(index.artifact, index.prepared, q, {
119
+ limit: MATCH_LIMIT,
120
+ types: typeKey ? typeKey.split(",") : undefined,
121
+ facets: facetKey ? facetKey.split(",") : undefined,
122
+ });
123
+ /*
124
+ * Terms come from the SAME parser the matcher used, so a query that
125
+ * normalises away ("!!!") reports zero terms and the page can render its
126
+ * "no searchable words" state — which is a different thing from "nothing
127
+ * matched", and the distinction the server tier also draws via
128
+ * `plan.empty`.
129
+ */
130
+ const terms = parseSearchTxtQuery(q);
131
+ return {
132
+ status,
133
+ result: toSearchResult(q, terms, hits, {
134
+ label,
135
+ moreHref: moreHrefResolver(index.artifact),
136
+ }),
137
+ suggestions: hits.slice(0, 8).map((h) => ({
138
+ objectID: h.href,
139
+ type: suggestionTypeFor(h.typeKey),
140
+ typeKey: h.typeKey,
141
+ title: h.title,
142
+ subtitle: h.detail || undefined,
143
+ url: h.href,
144
+ })),
145
+ facets: countFacets(hits),
146
+ builtAt: index.builtAt,
147
+ };
148
+ }, [index, status, query, typeKey, facetKey, label]);
149
+ }
@@ -1,7 +1,3 @@
1
- export * from "./types";
2
- export * from "./schemas";
3
- export * from "./columns";
4
- export * from "./hooks/useSearch";
5
1
  export * from "./hooks/useNavSuggestions";
6
2
  export * from "./components";
7
3
  export { manifest } from "./manifest";
@@ -1,7 +1,3 @@
1
- export * from "./types/index.js";
2
- export * from "./schemas/index.js";
3
- export * from "./columns/index.js";
4
- export * from "./hooks/useSearch.js";
5
1
  export * from "./hooks/useNavSuggestions.js";
6
2
  export * from "./components/index.js";
7
3
  export { manifest } from "./manifest.js";
@@ -1,2 +1,14 @@
1
1
  import type { FeatureManifest } from "../../contracts";
2
+ /**
3
+ * `default` is `SearchResultsClient`, which is what `[locale]/search/page.tsx`
4
+ * actually renders. It used to say `SearchView` — a component the route has
5
+ * never rendered, from the dead legacy `feat-search` subsystem — and A7
6
+ * (`audit-feature-manifest-routes`) is what this file is the fixed example
7
+ * for.
8
+ *
9
+ * `api/search` (the dead `SearchRepository`-backed GET handler) was removed
10
+ * from `apiRoutes` in the same Wave 10 commit that deleted the route itself
11
+ * — the manifest and the filesystem go empty together, not one claiming the
12
+ * other vanished a week early.
13
+ */
2
14
  export declare const manifest: FeatureManifest;
@@ -1,10 +1,25 @@
1
+ /**
2
+ * `default` is `SearchResultsClient`, which is what `[locale]/search/page.tsx`
3
+ * actually renders. It used to say `SearchView` — a component the route has
4
+ * never rendered, from the dead legacy `feat-search` subsystem — and A7
5
+ * (`audit-feature-manifest-routes`) is what this file is the fixed example
6
+ * for.
7
+ *
8
+ * `api/search` (the dead `SearchRepository`-backed GET handler) was removed
9
+ * from `apiRoutes` in the same Wave 10 commit that deleted the route itself
10
+ * — the manifest and the filesystem go empty together, not one claiming the
11
+ * other vanished a week early.
12
+ */
1
13
  export const manifest = {
2
14
  name: "search",
3
15
  i18nNamespace: "search",
4
16
  envKeys: [],
5
- routes: [{ segment: "[locale]/search", exports: { default: "SearchView" } }],
17
+ routes: [
18
+ { segment: "[locale]/search", exports: { default: "SearchResultsClient" } },
19
+ ],
6
20
  apiRoutes: [
7
- { segment: "api/search", methods: ["GET"] },
21
+ { segment: "api/search/scoped", methods: ["GET"] },
22
+ { segment: "api/search/suggestions", methods: ["GET"] },
8
23
  { segment: "api/categories/flat", methods: ["GET"] },
9
24
  ],
10
25
  };
@@ -1,4 +1 @@
1
- export * from "./actions";
2
- export { SearchRepository } from "./repository/search.repository";
3
1
  export { manifest } from "./manifest";
4
- export { GET as searchGET, GET } from "./api/route";
@@ -1,4 +1 @@
1
- export * from "./actions/index.js";
2
- export { SearchRepository } from "./repository/search.repository.js";
3
1
  export { manifest } from "./manifest.js";
4
- export { GET as searchGET, GET } from "./api/route.js";
@@ -53,7 +53,7 @@ export interface SellerListingTypeSpec {
53
53
  * because standard / auction / pre-order / prize-draw do NOT have one — their
54
54
  * store routes redirect into the multi-type `SellerProductsView`.
55
55
  */
56
- export type SellerListingTypeKey = "art" | "stickers" | "classified" | "digital-code" | "live";
56
+ export type SellerListingTypeKey = "art" | "stickers" | "classified" | "digital-code" | "live" | "spares";
57
57
  export declare const SELLER_LISTING_TYPE_SPECS: Record<SellerListingTypeKey, SellerListingTypeSpec>;
58
58
  export interface SellerListingTypeViewProps {
59
59
  onCreateClick?: () => void;
@@ -87,6 +87,26 @@ export const SELLER_LISTING_TYPE_SPECS = {
87
87
  }),
88
88
  extraColumns: [textCell("size", "Size")],
89
89
  },
90
+ spares: {
91
+ editRoute: (id) => String(ROUTES.STORE.SPARES_EDIT(id)),
92
+ newRoute: String(ROUTES.STORE.SPARES_NEW),
93
+ createLabel: "List a Spare",
94
+ bulkKey: "spares",
95
+ deleteLabel: "Spare Listing",
96
+ searchPlaceholder: "Search spares by part or colour...",
97
+ emptyLabel: "No spares listed yet — list a part you have going spare",
98
+ /*
99
+ * Colourway, not size. Two listings of the same part code are told apart by
100
+ * COLOUR here — a red Cross Dranzer and a navy one are different objects to
101
+ * a buyer rebuilding a specific top, which is the user's own framing
102
+ * ("sell it to someone who wants it in the same colour"). `printMeta.size`
103
+ * is meaningless on a moulded component.
104
+ */
105
+ extraFields: (item) => ({
106
+ colourway: toStringValue(item.colourway, ""),
107
+ }),
108
+ extraColumns: [textCell("colourway", "Colourway")],
109
+ },
90
110
  classified: {
91
111
  editRoute: (id) => String(ROUTES.STORE.CLASSIFIED_EDIT(id)),
92
112
  newRoute: String(ROUTES.STORE.CLASSIFIED_NEW),
@@ -46,9 +46,17 @@ const payoutSettingsDraftSchema = z.object({
46
46
  ifscCode: annotate(z.string(), { section: "method", quick: true, order: 5, row: "pair" }),
47
47
  bankName: annotate(z.string(), { section: "method", quick: true, order: 6, row: "pair" }),
48
48
  accountType: annotate(z.enum(["savings", "current"]), { section: "method", quick: true, order: 7, row: "pair" }),
49
+ // The three fields that identify the SUPPLIER OF RECORD on this store's
50
+ // invoices. A seller with a GSTIN invoices under it; one without
51
+ // invoices under LetItRip's (resolveSupplierIdentity).
52
+ //
53
+ // `pan` and `businessType` were removed 2026-10-19: neither exists on
54
+ // StoreDocument or UserDocument and the route stripped them, so a
55
+ // seller who entered a PAN was told it saved and it went nowhere.
56
+ // An input that provably cannot persist is worse than no input.
49
57
  gstin: annotate(z.string(), { section: "tax", sectionLabel: "Tax Info", order: 1, row: "pair" }),
50
- pan: annotate(z.string(), { section: "tax", order: 2, row: "pair" }),
51
- businessType: annotate(z.string(), { section: "tax", order: 3, row: "pair" }),
58
+ legalName: annotate(z.string(), { section: "tax", order: 2, row: "pair" }),
59
+ registeredAddress: annotate(z.string(), { section: "tax", order: 3, row: "full" }),
52
60
  autoPayout: annotate(z.boolean(), {
53
61
  section: "preferences", sectionLabel: "Preferences", order: 1, row: "quarter",
54
62
  }),
@@ -110,8 +118,8 @@ const DEFAULT_DRAFT = {
110
118
  bankName: "",
111
119
  accountType: "savings",
112
120
  gstin: "",
113
- pan: "",
114
- businessType: "",
121
+ legalName: "",
122
+ registeredAddress: "",
115
123
  autoPayout: true,
116
124
  minimumThreshold: "",
117
125
  emiEnabled: false,
@@ -142,9 +150,22 @@ export function SellerPayoutSettingsView({ apiBase = SELLER_ENDPOINTS.PAYOUT_SET
142
150
  ifscCode: details.bankAccount?.ifscCode ?? "",
143
151
  bankName: details.bankAccount?.bankName ?? "",
144
152
  accountType: details.bankAccount?.accountType ?? "savings",
145
- gstin: res?.data?.taxInfo?.gstin ?? "",
146
- pan: res?.data?.taxInfo?.pan ?? "",
147
- businessType: res?.data?.taxInfo?.businessType ?? "",
153
+ /*
154
+ * 🛑 Flat fields, NOT `res.data.taxInfo.*`.
155
+ *
156
+ * `taxInfo` is a key the route has never returned, so these three
157
+ * inputs were ALWAYS blank on load no matter what had been saved —
158
+ * and the save side posted a `taxInfo` object that the route's
159
+ * `z.object()` schema silently stripped. A seller could type their
160
+ * GSTIN, get a success toast, reload, and find it gone.
161
+ *
162
+ * The route now declares and persists `gstin` / `legalName` /
163
+ * `registeredAddress` on the STORE, because the GSTIN decides who
164
+ * is the supplier of record on that store's invoices.
165
+ */
166
+ gstin: res?.data?.gstin ?? "",
167
+ legalName: res?.data?.legalName ?? "",
168
+ registeredAddress: res?.data?.registeredAddress ?? "",
148
169
  autoPayout: res?.data?.preferences?.autoPayout ?? true,
149
170
  minimumThreshold: res?.data?.preferences?.minimumThreshold
150
171
  ? String(res.data.preferences.minimumThreshold)
@@ -184,11 +205,11 @@ export function SellerPayoutSettingsView({ apiBase = SELLER_ENDPOINTS.PAYOUT_SET
184
205
  pricesIncludeGst: draft.pricesIncludeGst,
185
206
  supportsShippingProtection: draft.supportsShippingProtection,
186
207
  supportsSaleProtection: draft.supportsSaleProtection,
187
- taxInfo: {
188
- gstin: draft.gstin.trim(),
189
- pan: draft.pan.trim(),
190
- businessType: draft.businessType.trim(),
191
- },
208
+ // Flat, matching the route's schema. A nested `taxInfo` object was
209
+ // stripped by `z.object()` and never reached Firestore.
210
+ gstin: draft.gstin.trim(),
211
+ legalName: draft.legalName.trim(),
212
+ registeredAddress: draft.registeredAddress.trim(),
192
213
  preferences: {
193
214
  autoPayout: draft.autoPayout,
194
215
  minimumThreshold: Math.round(parseFloat(draft.minimumThreshold || "0") * 100) / 100,
@@ -244,8 +265,8 @@ export function SellerPayoutSettingsView({ apiBase = SELLER_ENDPOINTS.PAYOUT_SET
244
265
  {
245
266
  id: "tax",
246
267
  label: "Tax Info",
247
- fields: ["gstin", "pan", "businessType"],
248
- render: ({ values, onChange }) => (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Tax Information" }), _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "Optional \u2014 required only for GST invoice generation and TDS compliance." }), _jsx(FormField, { name: "gstin", label: "GSTIN (optional)", type: "text", value: values.gstin, onChange: (v) => onChange({ gstin: v.toUpperCase() }), placeholder: "e.g. 22AAAAA0000A1Z5", helpText: "15-character Goods and Services Tax Identification Number.", disabled: busy }), _jsx(FormField, { name: "pan", label: "PAN (optional)", type: "text", value: values.pan, onChange: (v) => onChange({ pan: v.toUpperCase() }), placeholder: "e.g. ABCDE1234F", helpText: "Required for payouts above \u20B950,000 per year (TDS threshold).", disabled: busy }), _jsx(FormField, { name: "businessType", label: "Business Type (optional)", type: "text", value: values.businessType, onChange: (v) => onChange({ businessType: v }), placeholder: "e.g. Individual, Sole Proprietor, Private Limited", disabled: busy })] })),
268
+ fields: ["gstin", "legalName", "registeredAddress"],
269
+ render: ({ values, onChange }) => (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Tax Information" }), _jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "Optional. Enter a GSTIN and your orders are invoiced under your own registration; leave it blank and they are invoiced under LetItRip's." }), _jsx(FormField, { name: "gstin", label: "GSTIN (optional)", type: "text", value: values.gstin, onChange: (v) => onChange({ gstin: v.toUpperCase() }), placeholder: "e.g. 22AAAAA0000A1Z5", helpText: "15-character Goods and Services Tax Identification Number.", disabled: busy }), _jsx(FormField, { name: "legalName", label: "Registered legal name (optional)", type: "text", value: values.legalName, onChange: (v) => onChange({ legalName: v }), placeholder: "e.g. Arena Collectibles Pvt Ltd", helpText: "The entity name that appears on the invoice. Leave blank to use your store name.", disabled: busy }), _jsx(FormField, { name: "registeredAddress", label: "Registered address (optional)", type: "text", value: values.registeredAddress, onChange: (v) => onChange({ registeredAddress: v }), placeholder: "Address as registered against your GSTIN", helpText: "Printed on invoices issued under your GSTIN.", disabled: busy })] })),
249
270
  },
250
271
  {
251
272
  id: "preferences",
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
  import type { MediaField } from "../../media/types";
3
- export type ProductListingMode = "standard" | "auction" | "pre-order" | "prize-draw" | "bundle" | "classified" | "digital-code" | "live" | "art" | "stickers";
3
+ export type ProductListingMode = "standard" | "auction" | "pre-order" | "prize-draw" | "bundle" | "classified" | "digital-code" | "live" | "art" | "stickers" | "spares";
4
4
  export interface SellerProductDraft {
5
5
  title?: string;
6
6
  slug?: string;
@@ -8,6 +8,7 @@ import { FormShellContext, useFormShellState, applyZodIssues, FormErrorSummary }
8
8
  import { Alert, Button, Div, FormField, FormGroup, Heading, Section, Stack, TagInput, Text, Toggle, useToast, Row } from "../../../ui/index.js";
9
9
  import { ImageUpload, MediaUploadField, MediaUploadList, useMediaUpload } from "../../media/index.js";
10
10
  import { StoreAddressSelectorCreate } from "../../stores/components/StoreAddressSelectorCreate.js";
11
+ import { PriceGuidanceHint } from "../../categories/components/PriceGuidanceHint.js";
11
12
  import { QuickProductForm } from "./QuickProductForm.js";
12
13
  import { BarcodeField } from "./BarcodeField.js";
13
14
  import { pluginFor } from "../../../_internal/shared/listing-types/_registry.js";
@@ -388,7 +389,7 @@ const TYPE_SPECIFIC_SECTIONS = {
388
389
  function StepPricing({ values, onChange, listingType, }) {
389
390
  const listingPlugin = pluginForMode(listingType);
390
391
  const priceLabel = listingPlugin.priceLabel;
391
- return (_jsxs(Stack, { gap: "md", children: [_jsx(Alert, { variant: "info", children: "All prices in Indian Rupees (\u20B9)." }), _jsxs(FormGroup, { columns: 2, children: [_jsx(FormField, { name: "price", label: priceLabel, type: "number", value: toRupeesString(values.price), onChange: (v) => onChange({ price: fromRupeesString(v) }), placeholder: "999" }), _jsx(FormField, { name: "originalPrice", label: "Compare-at Price (\u20B9, optional)", type: "number", value: toRupeesString(values.originalPrice), onChange: (v) => onChange({ originalPrice: v ? fromRupeesString(v) : undefined }), placeholder: "1299", helpText: "Original price shown as strikethrough" })] }), listingPlugin.showsStockQuantity && (_jsx(FormField, { name: "stockQuantity", label: "Stock Quantity", type: "number", value: String(values.stockQuantity ?? ""), onChange: (v) => onChange({ stockQuantity: Number(v) }), placeholder: "1" })), _jsxs(FormGroup, { columns: 2, children: [_jsx(Toggle, { checked: !!values.featured, onChange: (checked) => onChange({ featured: checked }), label: "Mark as Featured" }), _jsx(Toggle, { checked: !!values.isNew, onChange: (checked) => onChange({ isNew: checked }), label: "Mark as New Arrival" })] }), _jsx(Toggle, { checked: !!values.allowOffers, onChange: (checked) => onChange({
392
+ return (_jsxs(Stack, { gap: "md", children: [_jsx(Alert, { variant: "info", children: "All prices in Indian Rupees (\u20B9)." }), _jsxs(FormGroup, { columns: 2, children: [_jsx(FormField, { name: "price", label: priceLabel, type: "number", value: toRupeesString(values.price), onChange: (v) => onChange({ price: fromRupeesString(v) }), placeholder: "999" }), _jsx(FormField, { name: "originalPrice", label: "Compare-at Price (\u20B9, optional)", type: "number", value: toRupeesString(values.originalPrice), onChange: (v) => onChange({ originalPrice: v ? fromRupeesString(v) : undefined }), placeholder: "1299", helpText: "Original price shown as strikethrough" })] }), (values.categoryIds?.[0] ?? values.category) && (_jsx(PriceGuidanceHint, { categoryId: (values.categoryIds?.[0] ?? values.category) })), listingPlugin.showsStockQuantity && (_jsx(FormField, { name: "stockQuantity", label: "Stock Quantity", type: "number", value: String(values.stockQuantity ?? ""), onChange: (v) => onChange({ stockQuantity: Number(v) }), placeholder: "1" })), _jsxs(FormGroup, { columns: 2, children: [_jsx(Toggle, { checked: !!values.featured, onChange: (checked) => onChange({ featured: checked }), label: "Mark as Featured" }), _jsx(Toggle, { checked: !!values.isNew, onChange: (checked) => onChange({ isNew: checked }), label: "Mark as New Arrival" })] }), _jsx(Toggle, { checked: !!values.allowOffers, onChange: (checked) => onChange({
392
393
  allowOffers: checked,
393
394
  minOfferPercent: checked
394
395
  ? values.minOfferPercent ?? DEFAULT_MIN_OFFER_PERCENT
@@ -24,7 +24,7 @@ const CLS_NAV_ICON_ACTIVE = "text-warning dark:text-warning";
24
24
  function NavLink({ item, isActive, onClick }) {
25
25
  return (_jsxs(Link, { href: item.href, onClick: onClick, className: `flex items-center justify-end gap-[var(--appkit-space-2-5)] rounded-lg px-[var(--appkit-space-3)] py-[var(--appkit-space-2)] text-[0.8125rem] font-medium leading-tight transition-colors ${isActive
26
26
  ? CLS_NAV_ACTIVE
27
- : "text-[var(--appkit-color-text-muted)] hover:bg-surface-hover hover:text-zinc-800 hover:text-[var(--appkit-color-text-muted)]"}`, children: [item.icon && _jsx(Span, { size: "base", className: "shrink-0 opacity-60", children: item.icon }), _jsx(Span, { className: "truncate", children: item.label }), item.badge != null && item.badge > 0 && (_jsx(Span, { weight: "bold", className: CLS_NAV_BADGE, children: item.badge }))] }));
27
+ : "text-[var(--appkit-color-text-muted)] hover:bg-surface-hover hover:text-[var(--appkit-color-text)]"}`, children: [item.icon && _jsx(Span, { size: "base", className: "shrink-0 opacity-60", children: item.icon }), _jsx(Span, { className: "truncate", children: item.label }), item.badge != null && item.badge > 0 && (_jsx(Span, { weight: "bold", className: CLS_NAV_BADGE, children: item.badge }))] }));
28
28
  }
29
29
  function FlatContent({ items, activeHref, storeName, storeLogoURL, onItemClick, }) {
30
30
  const activeItem = findActiveNavItem(items, activeHref);
@@ -0,0 +1,17 @@
1
+ /**
2
+ * SellerSparesView — seller browse/manage of spares listings.
3
+ *
4
+ * A named wrapper, matching its five siblings exactly: all behaviour is
5
+ * `SellerListingTypeView`, and everything this type does differently is one
6
+ * entry in `SELLER_LISTING_TYPE_SPECS` (a colourway column instead of a size
7
+ * column, and its own routes and copy).
8
+ *
9
+ * Written as a wrapper rather than as a sixth copy of the component on purpose
10
+ * — see `SellerListingTypeView`'s header for what the five hand-written copies
11
+ * cost, and note that the factory it adopts had existed with zero seller
12
+ * callers the whole time.
13
+ */
14
+ import React from "react";
15
+ import { type SellerListingTypeViewProps } from "./SellerListingTypeView";
16
+ export type SellerSparesViewProps = SellerListingTypeViewProps;
17
+ export declare function SellerSparesView(props: SellerSparesViewProps): React.JSX.Element;
@@ -0,0 +1,6 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { SellerListingTypeView, } from "./SellerListingTypeView.js";
4
+ export function SellerSparesView(props) {
5
+ return _jsx(SellerListingTypeView, { type: "spares", ...props });
6
+ }
@@ -114,6 +114,8 @@ export { SellerArtView } from "./SellerArtView";
114
114
  export type { SellerArtViewProps } from "./SellerArtView";
115
115
  export { SellerStickersView } from "./SellerStickersView";
116
116
  export type { SellerStickersViewProps } from "./SellerStickersView";
117
+ export { SellerSparesView } from "./SellerSparesView";
118
+ export type { SellerSparesViewProps } from "./SellerSparesView";
117
119
  export { SellerDigitalCodesView } from "./SellerDigitalCodesView";
118
120
  export type { SellerDigitalCodesViewProps } from "./SellerDigitalCodesView";
119
121
  export { SellerLiveView } from "./SellerLiveView";
@@ -60,6 +60,7 @@ export { SellerBundlesView } from "./SellerBundlesView.js";
60
60
  export { SellerClassifiedView } from "./SellerClassifiedView.js";
61
61
  export { SellerArtView } from "./SellerArtView.js";
62
62
  export { SellerStickersView } from "./SellerStickersView.js";
63
+ export { SellerSparesView } from "./SellerSparesView.js";
63
64
  export { SellerDigitalCodesView } from "./SellerDigitalCodesView.js";
64
65
  export { SellerLiveView } from "./SellerLiveView.js";
65
66
  export { BarcodeField } from "./BarcodeField.js";
@@ -60,7 +60,7 @@ export function CommandPalette({ isOpen, onClose, groups, placeholder = "Jump to
60
60
  if (target)
61
61
  navigate(target.href);
62
62
  }, [results, activeIndex, navigate, onClose]);
63
- return (_jsx(Modal, { isOpen: isOpen, onClose: onClose, size: "lg", showCloseButton: false, className: "appkit-command-palette", children: _jsxs(Stack, { gap: "sm", children: [_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Input, { ref: inputRef, value: query, onChange: (e) => setQuery(e.target.value), onKeyDown: handleKeyDown, placeholder: placeholder, "aria-label": placeholder, className: "flex-1", autoFocus: true }), _jsx(Kbd, { size: "sm", tone: "brand", children: "Esc" })] }), _jsx(Div, { className: "max-h-96", overflow: "y-auto", children: results.length === 0 ? (_jsxs(Text, { size: "sm", color: "muted", align: "center", paddingY: "lg", children: ["No matches for \u201C", query, "\u201D."] })) : (_jsx(Stack, { gap: "none", children: results.map((item, idx) => (_jsxs(Button, { variant: "ghost", type: "button", onClick: () => navigate(item.href), onMouseEnter: () => setActiveIndex(idx), justify: "between", rounded: "md", paddingX: "sm", paddingY: "xs", className: [
63
+ return (_jsx(Modal, { isOpen: isOpen, onClose: onClose, size: "lg", showCloseButton: false, children: _jsxs(Stack, { gap: "sm", children: [_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Input, { ref: inputRef, value: query, onChange: (e) => setQuery(e.target.value), onKeyDown: handleKeyDown, placeholder: placeholder, "aria-label": placeholder, className: "flex-1", autoFocus: true }), _jsx(Kbd, { size: "sm", tone: "brand", children: "Esc" })] }), _jsx(Div, { className: "max-h-96", overflow: "y-auto", children: results.length === 0 ? (_jsxs(Text, { size: "sm", color: "muted", align: "center", paddingY: "lg", children: ["No matches for \u201C", query, "\u201D."] })) : (_jsx(Stack, { gap: "none", children: results.map((item, idx) => (_jsxs(Button, { variant: "ghost", type: "button", onClick: () => navigate(item.href), onMouseEnter: () => setActiveIndex(idx), justify: "between", rounded: "md", paddingX: "sm", paddingY: "xs", className: [
64
64
  "w-full text-left",
65
65
  idx === activeIndex
66
66
  ? "bg-[var(--appkit-color-primary-50)] text-[var(--appkit-color-primary-700)]"
@@ -116,6 +116,25 @@ export interface SheetPart {
116
116
  * on these sheets.
117
117
  */
118
118
  duplicateOf?: number;
119
+ /**
120
+ * The `/media/{shortId}` slug of this part's PUBLIC, WATERMARKED copy.
121
+ *
122
+ * 🛑 ZERO BYTES ARE DUPLICATED. The `mediaAssets` row points at the SAME
123
+ * `assetPath` above — the clean original under `private/sticker-sheets/` —
124
+ * and is written with `watermarkedAt` deliberately ABSENT, so
125
+ * `/api/media/[...slug]` composites the mark on read. Clean original for the
126
+ * cut file, watermarked copy for the marketplace, one object.
127
+ *
128
+ * Object COUNT is metered separately from bytes (that is the whole reason the
129
+ * thumb atlas exists), so a second uploaded copy per part would spend Class A
130
+ * writes 60× faster per sheet for pixels we already have.
131
+ *
132
+ * Stored back here so re-promoting a sheet REUSES the row rather than minting
133
+ * a second slug for the same object and orphaning the first.
134
+ *
135
+ * Absent until the sheet has been promoted to listings.
136
+ */
137
+ mediaShortId?: string;
119
138
  }
120
139
  /**
121
140
  * One progress transition, mirrored from RTDB so history survives the prune.
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
  import type { ReactNode } from "react";
3
- export declare const getStoreBySlug: (slug: string) => Promise<import("@mohasinac/appkit").StoreDocument | null>;
3
+ export declare const getStoreBySlug: (slug: string) => Promise<import("..").StoreDocument | null>;
4
4
  export interface StoreDetailLayoutViewProps {
5
5
  storeSlug: string;
6
6
  /** The current active tab value: "products" | "auctions" | "reviews" | "about" */