@mohasinac/appkit 4.53.0 → 4.53.2

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 (520) hide show
  1. package/dist/.build-stamp.json +3 -3
  2. package/dist/_internal/client/scaffolds/AppShell.js +1 -1
  3. package/dist/_internal/client/theme/ThemeProvider.js +15 -1
  4. package/dist/_internal/server/features/auctions/og.d.ts +3 -1
  5. package/dist/_internal/server/features/auctions/og.js +3 -1
  6. package/dist/_internal/server/features/bundles/actions.js +1 -1
  7. package/dist/_internal/server/features/business-documents/download.d.ts +41 -0
  8. package/dist/_internal/server/features/business-documents/download.js +91 -0
  9. package/dist/_internal/server/features/categories/adapters.d.ts +1 -1
  10. package/dist/_internal/server/features/categories/adapters.js +10 -0
  11. package/dist/_internal/server/features/categories/price-guidance-resolve.d.ts +66 -0
  12. package/dist/_internal/server/features/categories/price-guidance-resolve.js +138 -0
  13. package/dist/_internal/server/features/checkout/actions.d.ts +14 -0
  14. package/dist/_internal/server/features/checkout/actions.js +106 -12
  15. package/dist/_internal/server/features/checkout/bundle-expansion.js +17 -0
  16. package/dist/_internal/server/features/checkout/data.d.ts +22 -0
  17. package/dist/_internal/server/features/checkout/group-rule-revalidation.d.ts +34 -0
  18. package/dist/_internal/server/features/checkout/group-rule-revalidation.js +124 -0
  19. package/dist/_internal/server/features/checkout/supplier-identity.d.ts +55 -0
  20. package/dist/_internal/server/features/checkout/supplier-identity.js +81 -0
  21. package/dist/_internal/server/features/classified/metadata.js +1 -1
  22. package/dist/_internal/server/features/classified/og.d.ts +3 -1
  23. package/dist/_internal/server/features/classified/og.js +3 -1
  24. package/dist/_internal/server/features/digital-code/metadata.js +1 -1
  25. package/dist/_internal/server/features/digital-code/og.d.ts +3 -1
  26. package/dist/_internal/server/features/digital-code/og.js +3 -1
  27. package/dist/_internal/server/features/digital-code/pool.d.ts +19 -4
  28. package/dist/_internal/server/features/digital-code/pool.js +19 -4
  29. package/dist/_internal/server/features/live/metadata.js +1 -1
  30. package/dist/_internal/server/features/live/og.d.ts +3 -1
  31. package/dist/_internal/server/features/live/og.js +3 -1
  32. package/dist/_internal/server/features/messages/actions.js +1 -1
  33. package/dist/_internal/server/features/parts/og.js +1 -1
  34. package/dist/_internal/server/features/pre-orders/og.d.ts +3 -1
  35. package/dist/_internal/server/features/pre-orders/og.js +3 -1
  36. package/dist/_internal/server/features/price-index/market.d.ts +57 -0
  37. package/dist/_internal/server/features/price-index/market.js +120 -0
  38. package/dist/_internal/server/features/price-index/search.d.ts +18 -0
  39. package/dist/_internal/server/features/price-index/search.js +47 -7
  40. package/dist/_internal/server/features/prize-draws/og.d.ts +3 -1
  41. package/dist/_internal/server/features/prize-draws/og.js +3 -1
  42. package/dist/_internal/server/features/products/group-members.d.ts +26 -0
  43. package/dist/_internal/server/features/products/group-members.js +7 -1
  44. package/dist/_internal/server/features/products/list-public.d.ts +12 -0
  45. package/dist/_internal/server/features/products/list-public.js +10 -1
  46. package/dist/_internal/server/features/products/listing-tab-counts.d.ts +25 -1
  47. package/dist/_internal/server/features/products/listing-tab-counts.js +128 -10
  48. package/dist/_internal/server/features/products/og.d.ts +3 -1
  49. package/dist/_internal/server/features/products/og.js +3 -1
  50. package/dist/_internal/server/features/search/scoped-sources.d.ts +26 -0
  51. package/dist/_internal/server/features/search/scoped-sources.js +252 -0
  52. package/dist/_internal/server/features/search/search-everything.d.ts +57 -0
  53. package/dist/_internal/server/features/search/search-everything.js +70 -20
  54. package/dist/_internal/server/features/seo/sitemap.js +6 -0
  55. package/dist/_internal/server/features/shared/listing-adapters.js +4 -2
  56. package/dist/_internal/server/features/sticker-trace/adapters.d.ts +11 -0
  57. package/dist/_internal/server/features/sticker-trace/adapters.js +1 -0
  58. package/dist/_internal/server/features/sticker-trace/promote-to-listings.d.ts +26 -0
  59. package/dist/_internal/server/features/sticker-trace/promote-to-listings.js +264 -0
  60. package/dist/_internal/server/features/sticker-trace/sheet-actions.d.ts +3 -1
  61. package/dist/_internal/server/features/sticker-trace/sheet-actions.js +32 -0
  62. package/dist/_internal/server/features/sticker-trace/storage.d.ts +20 -1
  63. package/dist/_internal/server/features/sticker-trace/storage.js +20 -1
  64. package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
  65. package/dist/_internal/server/features/stores/adapters.js +16 -0
  66. package/dist/_internal/server/features/stores/index.d.ts +1 -0
  67. package/dist/_internal/server/features/stores/index.js +1 -0
  68. package/dist/_internal/server/features/stores/tabs.d.ts +30 -0
  69. package/dist/_internal/server/features/stores/tabs.js +124 -0
  70. package/dist/_internal/shared/checkout/rules/_defaults.js +0 -2
  71. package/dist/_internal/shared/checkout/rules/_limits.d.ts +14 -1
  72. package/dist/_internal/shared/checkout/rules/_limits.js +14 -1
  73. package/dist/_internal/shared/checkout/rules/_registry.js +2 -0
  74. package/dist/_internal/shared/checkout/rules/auction.rule.js +9 -1
  75. package/dist/_internal/shared/checkout/rules/bundle.rule.js +13 -0
  76. package/dist/_internal/shared/checkout/rules/index.d.ts +2 -0
  77. package/dist/_internal/shared/checkout/rules/index.js +9 -0
  78. package/dist/_internal/shared/checkout/rules/offer.rule.js +0 -1
  79. package/dist/_internal/shared/checkout/rules/payment-gate.d.ts +26 -0
  80. package/dist/_internal/shared/checkout/rules/payment-gate.js +133 -0
  81. package/dist/_internal/shared/checkout/rules/prize-draw.rule.js +29 -8
  82. package/dist/_internal/shared/checkout/rules/spares.rule.d.ts +16 -0
  83. package/dist/_internal/shared/checkout/rules/spares.rule.js +5 -0
  84. package/dist/_internal/shared/checkout/rules/types.d.ts +26 -2
  85. package/dist/_internal/shared/config/schema.d.ts +122 -0
  86. package/dist/_internal/shared/features/cart/schema.js +3 -2
  87. package/dist/_internal/shared/features/products/group-rules.d.ts +75 -0
  88. package/dist/_internal/shared/features/products/group-rules.js +142 -0
  89. package/dist/_internal/shared/listing-types/_registry.d.ts +24 -0
  90. package/dist/_internal/shared/listing-types/_registry.js +39 -1
  91. package/dist/_internal/shared/listing-types/art/config.d.ts +1 -0
  92. package/dist/_internal/shared/listing-types/art/config.js +2 -0
  93. package/dist/_internal/shared/listing-types/auction/config.d.ts +1 -0
  94. package/dist/_internal/shared/listing-types/auction/config.js +2 -0
  95. package/dist/_internal/shared/listing-types/availability.js +48 -0
  96. package/dist/_internal/shared/listing-types/capabilities.js +19 -0
  97. package/dist/_internal/shared/listing-types/classified/config.d.ts +1 -0
  98. package/dist/_internal/shared/listing-types/classified/config.js +2 -0
  99. package/dist/_internal/shared/listing-types/digital-code/config.d.ts +1 -0
  100. package/dist/_internal/shared/listing-types/digital-code/config.js +2 -0
  101. package/dist/_internal/shared/listing-types/feature-flags.js +1 -0
  102. package/dist/_internal/shared/listing-types/live/config.d.ts +1 -0
  103. package/dist/_internal/shared/listing-types/live/config.js +2 -0
  104. package/dist/_internal/shared/listing-types/pre-order/config.d.ts +1 -0
  105. package/dist/_internal/shared/listing-types/pre-order/config.js +2 -0
  106. package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +1 -0
  107. package/dist/_internal/shared/listing-types/prize-draw/config.js +2 -0
  108. package/dist/_internal/shared/listing-types/spares/config.d.ts +74 -0
  109. package/dist/_internal/shared/listing-types/spares/config.js +60 -0
  110. package/dist/_internal/shared/listing-types/spares/ctas.d.ts +1 -0
  111. package/dist/_internal/shared/listing-types/spares/ctas.js +4 -0
  112. package/dist/_internal/shared/listing-types/spares/og.js +1 -0
  113. package/dist/_internal/shared/listing-types/spares/schema.d.ts +2 -0
  114. package/dist/_internal/shared/listing-types/spares/schema.js +3 -0
  115. package/dist/_internal/shared/listing-types/spares/seed-factory.d.ts +1 -0
  116. package/dist/_internal/shared/listing-types/spares/seed-factory.js +1 -0
  117. package/dist/_internal/shared/listing-types/standard/config.d.ts +1 -0
  118. package/dist/_internal/shared/listing-types/standard/config.js +2 -0
  119. package/dist/_internal/shared/listing-types/stickers/config.d.ts +1 -0
  120. package/dist/_internal/shared/listing-types/stickers/config.js +2 -0
  121. package/dist/_internal/shared/search/match.d.ts +11 -0
  122. package/dist/_internal/shared/search/match.js +30 -3
  123. package/dist/_internal/shared/search/to-groups.d.ts +52 -0
  124. package/dist/_internal/shared/search/to-groups.js +141 -0
  125. package/dist/client.d.ts +8 -2
  126. package/dist/client.js +4 -1
  127. package/dist/constants/api-endpoints.d.ts +46 -15
  128. package/dist/constants/api-endpoints.js +35 -5
  129. package/dist/constants/cache-invalidation.js +3 -1
  130. package/dist/constants/field-names.d.ts +6 -0
  131. package/dist/constants/field-names.js +6 -0
  132. package/dist/features/about/components/PolicyPageView.d.ts +22 -2
  133. package/dist/features/about/components/PolicyPageView.js +14 -2
  134. package/dist/features/about/components/PublicProfileView.js +2 -1
  135. package/dist/features/about/components/ShippingPolicyView.js +42 -2
  136. package/dist/features/account/components/NotificationBell.js +1 -1
  137. package/dist/features/account/hooks/useProfileStats.js +5 -1
  138. package/dist/features/addresses/repository/addresses.repository.d.ts +16 -0
  139. package/dist/features/addresses/repository/addresses.repository.js +21 -0
  140. package/dist/features/admin/actions/admin-actions.js +16 -1
  141. package/dist/features/admin/components/AdminCategoryEditorView.js +19 -2
  142. package/dist/features/admin/components/AdminNavigationView.js +1 -1
  143. package/dist/features/admin/components/AdminPageHeader.js +1 -1
  144. package/dist/features/admin/components/AdminProductEditorView.js +17 -2
  145. package/dist/features/admin/components/AdminSidebar.js +1 -1
  146. package/dist/features/admin/components/AdminSiteSettingsView.js +39 -8
  147. package/dist/features/admin/components/AdminSparesView.d.ts +12 -0
  148. package/dist/features/admin/components/AdminSparesView.js +30 -0
  149. package/dist/features/admin/components/AdminUsersView.js +9 -7
  150. package/dist/features/admin/components/index.d.ts +2 -0
  151. package/dist/features/admin/components/index.js +1 -0
  152. package/dist/features/admin/components/sections/adminSectionsTypes.js +7 -0
  153. package/dist/features/admin/constants/filter-tabs.d.ts +3 -0
  154. package/dist/features/admin/constants/filter-tabs.js +1 -0
  155. package/dist/features/admin/schemas/firestore.d.ts +26 -2
  156. package/dist/features/auctions/components/AuctionDetailPageView.js +12 -18
  157. package/dist/features/auth/repository/user.repository.d.ts +13 -0
  158. package/dist/features/auth/repository/user.repository.js +28 -0
  159. package/dist/features/auth/schemas/firestore.d.ts +2 -0
  160. package/dist/features/auth/schemas/firestore.js +2 -0
  161. package/dist/features/business-documents/repository/business-documents.repository.d.ts +58 -0
  162. package/dist/features/business-documents/repository/business-documents.repository.js +54 -0
  163. package/dist/features/business-documents/schemas/firestore.d.ts +105 -0
  164. package/dist/features/business-documents/schemas/firestore.js +75 -0
  165. package/dist/features/cart/actions/cart-actions.js +83 -6
  166. package/dist/features/cart/repository/cart.repository.js +32 -4
  167. package/dist/features/cart/schemas/firestore.d.ts +20 -0
  168. package/dist/features/cart/schemas/index.d.ts +2 -2
  169. package/dist/features/catalogue/components/PublicCatalogueItemDetailView.js +1 -1
  170. package/dist/features/categories/api/[id]/price-guidance/route.d.ts +42 -0
  171. package/dist/features/categories/api/[id]/price-guidance/route.js +90 -0
  172. package/dist/features/categories/components/BrandDetailPageView.js +32 -8
  173. package/dist/features/categories/components/BrandDetailTabs.d.ts +7 -1
  174. package/dist/features/categories/components/BrandDetailTabs.js +28 -3
  175. package/dist/features/categories/components/BundleCollage.js +3 -2
  176. package/dist/features/categories/components/BundleItemsPicker.js +3 -4
  177. package/dist/features/categories/components/CategoriesIndexListing.js +23 -8
  178. package/dist/features/categories/components/CategoryDetailPageView.js +157 -20
  179. package/dist/features/categories/components/CategoryDetailTabs.d.ts +7 -1
  180. package/dist/features/categories/components/CategoryDetailTabs.js +41 -7
  181. package/dist/features/categories/components/CategoryGrid.js +10 -1
  182. package/dist/features/categories/components/PriceGuidanceHint.d.ts +29 -0
  183. package/dist/features/categories/components/PriceGuidanceHint.js +61 -0
  184. package/dist/features/categories/components/SubcategoryCardRow.d.ts +27 -0
  185. package/dist/features/categories/components/SubcategoryCardRow.js +98 -0
  186. package/dist/features/categories/constants/category-tabs.d.ts +20 -25
  187. package/dist/features/categories/constants/category-tabs.js +22 -39
  188. package/dist/features/categories/repository/categories.repository.d.ts +12 -0
  189. package/dist/features/categories/repository/categories.repository.js +20 -0
  190. package/dist/features/categories/schemas/firestore.d.ts +22 -1
  191. package/dist/features/categories/schemas/firestore.js +10 -0
  192. package/dist/features/categories/schemas/index.d.ts +6 -0
  193. package/dist/features/categories/schemas/index.js +2 -0
  194. package/dist/features/categories/types/index.d.ts +8 -0
  195. package/dist/features/categories/utils/taxonomy-visual.d.ts +16 -3
  196. package/dist/features/categories/utils/taxonomy-visual.js +26 -10
  197. package/dist/features/classified/components/ClassifiedDetailPageView.js +14 -10
  198. package/dist/features/contact/components/ContactPageView.d.ts +33 -1
  199. package/dist/features/contact/components/ContactPageView.js +58 -28
  200. package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +14 -10
  201. package/dist/features/grouped/components/GroupedListingDetailView.js +9 -1
  202. package/dist/features/grouped/schemas/firestore.d.ts +5 -0
  203. package/dist/features/homepage/actions/homepage-section-actions.d.ts +3 -3
  204. package/dist/features/homepage/components/CollectionCardsSection.d.ts +28 -6
  205. package/dist/features/homepage/components/CollectionCardsSection.js +43 -8
  206. package/dist/features/homepage/components/HowItWorksSection.d.ts +23 -6
  207. package/dist/features/homepage/components/HowItWorksSection.js +4 -4
  208. package/dist/features/homepage/components/PromoGrid.d.ts +31 -2
  209. package/dist/features/homepage/components/PromoGrid.js +12 -3
  210. package/dist/features/homepage/components/TestimonialsCarousel.d.ts +34 -2
  211. package/dist/features/homepage/components/TestimonialsCarousel.js +1 -1
  212. package/dist/features/homepage/components/index.d.ts +0 -20
  213. package/dist/features/homepage/components/index.js +0 -11
  214. package/dist/features/homepage/index.d.ts +0 -2
  215. package/dist/features/homepage/index.js +0 -2
  216. package/dist/features/homepage/lib/section-renderer.d.ts +9 -0
  217. package/dist/features/homepage/lib/section-renderer.js +202 -58
  218. package/dist/features/homepage/repository/homepage-sections.repository.d.ts +35 -3
  219. package/dist/features/homepage/repository/homepage-sections.repository.js +58 -8
  220. package/dist/features/homepage/schemas/firestore.d.ts +106 -3
  221. package/dist/features/homepage/schemas/firestore.js +32 -2
  222. package/dist/features/homepage/schemas/index.d.ts +36 -7
  223. package/dist/features/homepage/schemas/index.js +39 -27
  224. package/dist/features/homepage/server.d.ts +0 -3
  225. package/dist/features/homepage/server.js +0 -3
  226. package/dist/features/homepage/types/index.d.ts +0 -47
  227. package/dist/features/homepage/types/index.js +49 -0
  228. package/dist/features/layout/AppLayoutShell.js +1 -1
  229. package/dist/features/layout/BottomNavItem.js +1 -1
  230. package/dist/features/layout/BottomSheet.js +1 -1
  231. package/dist/features/layout/TitleBarLayout.js +1 -1
  232. package/dist/features/live/components/LiveItemDetailPageView.js +14 -10
  233. package/dist/features/media/hooks/useMedia.js +17 -0
  234. package/dist/features/media/repository/media-assets.repository.d.ts +46 -0
  235. package/dist/features/media/repository/media-assets.repository.js +31 -0
  236. package/dist/features/media/trust-signals.d.ts +85 -0
  237. package/dist/features/media/trust-signals.js +126 -0
  238. package/dist/features/parts/components/PartDetailPageView.d.ts +14 -1
  239. package/dist/features/parts/components/PartDetailPageView.js +2 -2
  240. package/dist/features/parts/components/PartsIndexPageView.d.ts +11 -2
  241. package/dist/features/parts/components/PartsIndexPageView.js +2 -2
  242. package/dist/features/parts/components/PartsSearchBox.d.ts +9 -0
  243. package/dist/features/parts/components/PartsSearchBox.js +57 -0
  244. package/dist/features/parts/schemas/firestore.d.ts +149 -3
  245. package/dist/features/parts/schemas/firestore.js +184 -0
  246. package/dist/features/payments/repository/payout.repository.d.ts +15 -0
  247. package/dist/features/payments/repository/payout.repository.js +21 -0
  248. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +12 -18
  249. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +1 -1
  250. package/dist/features/price-index/components/PriceIndexToolView.d.ts +24 -1
  251. package/dist/features/price-index/components/PriceIndexToolView.js +299 -17
  252. package/dist/features/price-index/lookup-target.d.ts +48 -0
  253. package/dist/features/price-index/lookup-target.js +107 -0
  254. package/dist/features/products/components/AvailabilityScopeHint.d.ts +22 -0
  255. package/dist/features/products/components/AvailabilityScopeHint.js +27 -0
  256. package/dist/features/products/components/CompareOverlay.d.ts +20 -2
  257. package/dist/features/products/components/CompareOverlay.js +23 -3
  258. package/dist/features/products/components/CustomSectionTabContent.d.ts +31 -0
  259. package/dist/features/products/components/CustomSectionTabContent.js +29 -3
  260. package/dist/features/products/components/GroupMemberPicker.d.ts +19 -1
  261. package/dist/features/products/components/GroupMemberPicker.js +46 -8
  262. package/dist/features/products/components/GroupSettingsPanel.d.ts +11 -1
  263. package/dist/features/products/components/GroupSettingsPanel.js +92 -3
  264. package/dist/features/products/components/PrizeDrawDetailPageView.js +1 -1
  265. package/dist/features/products/components/PrizeDrawEntryActions.d.ts +15 -1
  266. package/dist/features/products/components/PrizeDrawEntryActions.js +70 -8
  267. package/dist/features/products/components/ProductDetailPageView.js +81 -17
  268. package/dist/features/products/components/ProductForm.d.ts +13 -1
  269. package/dist/features/products/components/ProductForm.js +16 -2
  270. package/dist/features/products/components/ProductsIndexListing.d.ts +16 -1
  271. package/dist/features/products/components/ProductsIndexListing.js +3 -3
  272. package/dist/features/products/components/ShowGroupSection.js +15 -2
  273. package/dist/features/products/components/SparesListView.d.ts +7 -0
  274. package/dist/features/products/components/SparesListView.js +39 -0
  275. package/dist/features/products/components/SublistingCarouselSection.js +2 -1
  276. package/dist/features/products/constants/action-defs.d.ts +1 -0
  277. package/dist/features/products/constants/action-defs.js +1 -0
  278. package/dist/features/products/repository/products.repository.d.ts +99 -0
  279. package/dist/features/products/repository/products.repository.js +240 -18
  280. package/dist/features/products/schemas/firestore.d.ts +97 -4
  281. package/dist/features/products/schemas/firestore.js +104 -0
  282. package/dist/features/products/schemas/index.d.ts +10 -19
  283. package/dist/features/products/schemas/index.js +23 -6
  284. package/dist/features/products/types/index.d.ts +45 -1
  285. package/dist/features/products/utils/group-member-image.d.ts +46 -0
  286. package/dist/features/products/utils/group-member-image.js +4 -0
  287. package/dist/features/products/utils/listing-badge-variant.js +4 -0
  288. package/dist/features/reviews/components/ReviewsList.js +1 -1
  289. package/dist/features/scams/components/ScamProfileView.js +1 -1
  290. package/dist/features/search/components/EntityTypeahead.d.ts +44 -0
  291. package/dist/features/search/components/EntityTypeahead.js +92 -0
  292. package/dist/features/search/components/Search.d.ts +12 -1
  293. package/dist/features/search/components/Search.js +47 -3
  294. package/dist/features/search/components/SearchFacetRail.d.ts +11 -0
  295. package/dist/features/search/components/SearchFacetRail.js +92 -0
  296. package/dist/features/search/components/SearchResultsClient.d.ts +33 -0
  297. package/dist/features/search/components/SearchResultsClient.js +103 -0
  298. package/dist/features/search/components/SearchResultsPageView.d.ts +15 -1
  299. package/dist/features/search/components/SearchResultsPageView.js +2 -2
  300. package/dist/features/search/components/index.d.ts +0 -6
  301. package/dist/features/search/components/index.js +0 -3
  302. package/dist/features/search/hooks/useNavSuggestions.d.ts +13 -0
  303. package/dist/features/search/hooks/useScopedSearch.d.ts +34 -0
  304. package/dist/features/search/hooks/useScopedSearch.js +114 -0
  305. package/dist/features/search/hooks/useSiteSearch.d.ts +26 -0
  306. package/dist/features/search/hooks/useSiteSearch.js +149 -0
  307. package/dist/features/search/index.d.ts +0 -4
  308. package/dist/features/search/index.js +0 -4
  309. package/dist/features/search/manifest.d.ts +12 -0
  310. package/dist/features/search/manifest.js +17 -2
  311. package/dist/features/search/server.d.ts +0 -3
  312. package/dist/features/search/server.js +0 -3
  313. package/dist/features/seller/components/SellerListingTypeView.d.ts +1 -1
  314. package/dist/features/seller/components/SellerListingTypeView.js +20 -0
  315. package/dist/features/seller/components/SellerPayoutSettingsView.js +35 -14
  316. package/dist/features/seller/components/SellerProductShell.d.ts +1 -1
  317. package/dist/features/seller/components/SellerProductShell.js +2 -1
  318. package/dist/features/seller/components/SellerProductsView.js +3 -2
  319. package/dist/features/seller/components/SellerSidebar.js +1 -1
  320. package/dist/features/seller/components/SellerSparesView.d.ts +17 -0
  321. package/dist/features/seller/components/SellerSparesView.js +6 -0
  322. package/dist/features/seller/components/index.d.ts +2 -0
  323. package/dist/features/seller/components/index.js +1 -0
  324. package/dist/features/shell/CommandPalette.js +1 -1
  325. package/dist/features/sticker-trace/schemas/firestore.d.ts +19 -0
  326. package/dist/features/stores/components/StoreAuctionsListing.js +2 -1
  327. package/dist/features/stores/components/StoreDetailLayoutView.d.ts +1 -1
  328. package/dist/features/stores/components/StoreDetailLayoutView.js +7 -82
  329. package/dist/features/stores/components/StoreHeader.js +1 -2
  330. package/dist/features/stores/components/StoreSparesPageView.d.ts +27 -0
  331. package/dist/features/stores/components/StoreSparesPageView.js +48 -0
  332. package/dist/features/stores/schemas/firestore.d.ts +19 -0
  333. package/dist/features/tester/seed-data/authored/buying__spares-and-groups.d.ts +2 -0
  334. package/dist/features/tester/seed-data/authored/buying__spares-and-groups.js +96 -0
  335. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.d.ts +2 -0
  336. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.js +392 -45
  337. package/dist/features/tester/seed-data/authored/content-discovery__category-tabs-franchise-bundles.js +54 -32
  338. package/dist/features/tester/seed-data/authored/content-discovery__parts-database.js +3 -2
  339. package/dist/features/tester/seed-data/authored/content-discovery__price-index-and-compare.d.ts +2 -0
  340. package/dist/features/tester/seed-data/authored/content-discovery__price-index-and-compare.js +73 -0
  341. package/dist/features/tester/seed-data/authored/content-discovery__site-wide-index.d.ts +2 -0
  342. package/dist/features/tester/seed-data/authored/content-discovery__site-wide-index.js +340 -0
  343. package/dist/features/tester/seed-data/authored/index.js +16 -0
  344. package/dist/features/tester/seed-data/authored/search-and-nav__header-search.d.ts +1 -0
  345. package/dist/features/tester/seed-data/authored/search-and-nav__header-search.js +57 -0
  346. package/dist/features/tester/seed-data/authored/selling__spares-and-group-editing.d.ts +2 -0
  347. package/dist/features/tester/seed-data/authored/selling__spares-and-group-editing.js +77 -0
  348. package/dist/features/tester/seed-data/authored/tools__sticker-promote-to-listings.d.ts +2 -0
  349. package/dist/features/tester/seed-data/authored/tools__sticker-promote-to-listings.js +58 -0
  350. package/dist/features/tester/seed-data/authored/tools__sticker-tracer.js +5 -4
  351. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +384 -18
  352. package/dist/index.d.ts +17 -57
  353. package/dist/index.js +35 -96
  354. package/dist/next/routing/route-map.d.ts +42 -1
  355. package/dist/next/routing/route-map.js +45 -0
  356. package/dist/providers/db-firebase/base.repository.d.ts +22 -0
  357. package/dist/providers/db-firebase/base.repository.js +36 -0
  358. package/dist/schemas/registry.d.ts +15 -6
  359. package/dist/security/blind-index-tokens.d.ts +54 -0
  360. package/dist/security/blind-index-tokens.js +152 -0
  361. package/dist/security/index.d.ts +1 -1
  362. package/dist/security/index.js +1 -1
  363. package/dist/security/settings-encryption.d.ts +35 -0
  364. package/dist/security/settings-encryption.js +91 -0
  365. package/dist/seed/_helpers/brand-rows.js +38 -14
  366. package/dist/seed/_helpers/category-forest.js +73 -7
  367. package/dist/seed/_helpers/category-images-generated.d.ts +25 -6
  368. package/dist/seed/_helpers/category-images-generated.js +81 -6
  369. package/dist/seed/_helpers/category-models.d.ts +1 -1
  370. package/dist/seed/_helpers/category-models.js +7 -1
  371. package/dist/seed/_helpers/category-parts-glossary-map.js +8 -0
  372. package/dist/seed/_helpers/category-parts.d.ts +1 -1
  373. package/dist/seed/_helpers/category-parts.js +50 -2
  374. package/dist/seed/_helpers/character-features.d.ts +1 -1
  375. package/dist/seed/_helpers/character-features.js +2 -1
  376. package/dist/seed/_helpers/franchise-rows.js +10 -2
  377. package/dist/seed/_helpers/media.d.ts +47 -0
  378. package/dist/seed/_helpers/media.js +34 -0
  379. package/dist/seed/authenticity-knowledge-seed-data.d.ts +49 -5
  380. package/dist/seed/authenticity-knowledge-seed-data.js +10001 -549
  381. package/dist/seed/categories-seed-data.js +124 -20
  382. package/dist/seed/grouped-listings-seed-data.js +16 -0
  383. package/dist/seed/homepage-sections-seed-data.js +94 -5
  384. package/dist/seed/index.d.ts +2 -3
  385. package/dist/seed/index.js +2 -2
  386. package/dist/seed/manifest.js +3 -0
  387. package/dist/seed/media-assets-seed-data.d.ts +1 -1
  388. package/dist/seed/media-assets-seed-data.js +746 -196
  389. package/dist/seed/model-composition-seed-data.js +122 -6
  390. package/dist/seed/part-glossary-seed-data.d.ts +1 -1
  391. package/dist/seed/part-glossary-seed-data.js +37219 -463
  392. package/dist/seed/products-art-seed-data.js +7 -18
  393. package/dist/seed/products-auctions-seed-data.js +56 -47
  394. package/dist/seed/products-beyblade-x-seed-data.d.ts +2 -0
  395. package/dist/seed/products-beyblade-x-seed-data.js +476 -0
  396. package/dist/seed/products-catalogue-seed-data.d.ts +5 -5
  397. package/dist/seed/products-catalogue-seed-data.js +1500 -1240
  398. package/dist/seed/products-classifieds-seed-data.js +9 -27
  399. package/dist/seed/products-digital-codes-seed-data.js +9 -18
  400. package/dist/seed/products-live-items-seed-data.js +5 -13
  401. package/dist/seed/products-preorders-seed-data.js +67 -33
  402. package/dist/seed/products-prize-draws-seed-data.js +8 -17
  403. package/dist/seed/products-spares-seed-data.d.ts +2 -0
  404. package/dist/seed/products-spares-seed-data.js +368 -0
  405. package/dist/seed/products-standard-seed-data.js +39 -126
  406. package/dist/seed/products-stickers-seed-data.js +59 -15
  407. package/dist/seed/site-settings-seed-data.js +8 -0
  408. package/dist/seo/json-ld.d.ts +25 -0
  409. package/dist/seo/json-ld.js +28 -0
  410. package/dist/server-entry.d.ts +3 -1
  411. package/dist/server-entry.js +2 -2
  412. package/dist/server.d.ts +11 -9
  413. package/dist/server.js +35 -25
  414. package/dist/styles.css +202 -1
  415. package/dist/tailwind-input.css +31 -17
  416. package/dist/tailwind-utilities.css +1 -1
  417. package/dist/ui/components/Accordion.js +1 -1
  418. package/dist/ui/components/Breadcrumb.js +1 -1
  419. package/dist/ui/components/DetailPageGallery.js +0 -2
  420. package/dist/ui/components/DetailPageHero.js +0 -1
  421. package/dist/ui/components/DetailPageTabs.js +1 -1
  422. package/dist/ui/components/Divider.js +3 -3
  423. package/dist/ui/components/GatedPrice.js +5 -1
  424. package/dist/ui/components/HorizontalScroller.js +1 -1
  425. package/dist/ui/components/ListingLayout.js +3 -3
  426. package/dist/ui/components/MediaTabs.style.css +81 -0
  427. package/dist/ui/components/Pagination.js +1 -1
  428. package/dist/ui/components/PendingValue.d.ts +45 -0
  429. package/dist/ui/components/PendingValue.js +7 -0
  430. package/dist/ui/components/Radio.style.css +119 -0
  431. package/dist/ui/components/RatingDisplay.js +2 -2
  432. package/dist/ui/components/SettingsSection.js +0 -2
  433. package/dist/ui/components/SiteLogo.js +3 -0
  434. package/dist/ui/components/SiteMark.js +3 -0
  435. package/dist/ui/components/SortDropdown.js +1 -1
  436. package/dist/ui/components/SpecTable.d.ts +58 -0
  437. package/dist/ui/components/SpecTable.js +8 -0
  438. package/dist/ui/components/StarRating.js +1 -3
  439. package/dist/ui/components/SummaryCard.js +1 -1
  440. package/dist/ui/components/index.style.css +1 -0
  441. package/dist/ui/icons/icon-registry.d.ts +1 -0
  442. package/dist/ui/icons/icon-registry.js +9 -1
  443. package/dist/ui/index.d.ts +4 -0
  444. package/dist/ui/index.js +2 -0
  445. package/dist/utils/search-txt-query.d.ts +12 -0
  446. package/dist/utils/search-txt-query.js +12 -0
  447. package/package.json +1 -1
  448. package/scripts/dedupe-peer-deps.mjs +18 -0
  449. package/scripts/seed-cli.mjs +250 -35
  450. package/scripts/verify-css-build.mjs +118 -37
  451. package/dist/_internal/server/features/search/actions.d.ts +0 -7
  452. package/dist/_internal/server/features/search/actions.js +0 -21
  453. package/dist/_internal/server/features/search/data.d.ts +0 -15
  454. package/dist/_internal/server/features/search/data.js +0 -18
  455. package/dist/_internal/server/features/search/index.d.ts +0 -3
  456. package/dist/_internal/server/features/search/index.js +0 -2
  457. package/dist/features/homepage/api/[id]/route.d.ts +0 -23
  458. package/dist/features/homepage/api/[id]/route.js +0 -103
  459. package/dist/features/homepage/api/route.d.ts +0 -14
  460. package/dist/features/homepage/api/route.js +0 -140
  461. package/dist/features/homepage/api/sections/[id]/route.d.ts +0 -26
  462. package/dist/features/homepage/api/sections/[id]/route.js +0 -95
  463. package/dist/features/homepage/api/sections/route.d.ts +0 -13
  464. package/dist/features/homepage/api/sections/route.js +0 -82
  465. package/dist/features/homepage/components/AdvertisementBanner.d.ts +0 -14
  466. package/dist/features/homepage/components/AdvertisementBanner.js +0 -35
  467. package/dist/features/homepage/components/BeforeAfterCard.d.ts +0 -9
  468. package/dist/features/homepage/components/BeforeAfterCard.js +0 -73
  469. package/dist/features/homepage/components/FeaturedResultsSection.d.ts +0 -17
  470. package/dist/features/homepage/components/FeaturedResultsSection.js +0 -17
  471. package/dist/features/homepage/components/HeroBanner.d.ts +0 -7
  472. package/dist/features/homepage/components/HeroBanner.js +0 -43
  473. package/dist/features/homepage/components/HeroSection.d.ts +0 -7
  474. package/dist/features/homepage/components/HeroSection.js +0 -6
  475. package/dist/features/homepage/components/HomepageSkeleton.d.ts +0 -2
  476. package/dist/features/homepage/components/HomepageSkeleton.js +0 -21
  477. package/dist/features/homepage/components/HomepageView.d.ts +0 -25
  478. package/dist/features/homepage/components/HomepageView.js +0 -5
  479. package/dist/features/homepage/components/NewsletterBanner.d.ts +0 -23
  480. package/dist/features/homepage/components/NewsletterBanner.js +0 -37
  481. package/dist/features/homepage/components/SiteFeaturesSection.d.ts +0 -14
  482. package/dist/features/homepage/components/SiteFeaturesSection.js +0 -11
  483. package/dist/features/homepage/components/TrustBadges.d.ts +0 -6
  484. package/dist/features/homepage/components/TrustBadges.js +0 -46
  485. package/dist/features/homepage/components/TrustIndicatorsSection.d.ts +0 -12
  486. package/dist/features/homepage/components/TrustIndicatorsSection.js +0 -11
  487. package/dist/features/homepage/hooks/useHomepage.d.ts +0 -11
  488. package/dist/features/homepage/hooks/useHomepage.js +0 -17
  489. package/dist/features/homepage/hooks/useHomepageSections.d.ts +0 -2
  490. package/dist/features/homepage/hooks/useHomepageSections.js +0 -10
  491. package/dist/features/homepage/repository/homepage.repository.d.ts +0 -11
  492. package/dist/features/homepage/repository/homepage.repository.js +0 -25
  493. package/dist/features/search/actions/index.d.ts +0 -1
  494. package/dist/features/search/actions/index.js +0 -1
  495. package/dist/features/search/actions/search-actions.d.ts +0 -18
  496. package/dist/features/search/actions/search-actions.js +0 -43
  497. package/dist/features/search/api/route.d.ts +0 -22
  498. package/dist/features/search/api/route.js +0 -128
  499. package/dist/features/search/columns/index.d.ts +0 -17
  500. package/dist/features/search/columns/index.js +0 -49
  501. package/dist/features/search/components/SearchFiltersRow.d.ts +0 -22
  502. package/dist/features/search/components/SearchFiltersRow.js +0 -21
  503. package/dist/features/search/components/SearchResultsSection.d.ts +0 -53
  504. package/dist/features/search/components/SearchResultsSection.js +0 -35
  505. package/dist/features/search/components/SearchView.d.ts +0 -27
  506. package/dist/features/search/components/SearchView.js +0 -8
  507. package/dist/features/search/hooks/useSearch.d.ts +0 -21
  508. package/dist/features/search/hooks/useSearch.js +0 -33
  509. package/dist/features/search/repository/search.repository.d.ts +0 -14
  510. package/dist/features/search/repository/search.repository.js +0 -59
  511. package/dist/features/search/schemas/index.d.ts +0 -70
  512. package/dist/features/search/schemas/index.js +0 -36
  513. package/dist/features/search/types/index.d.ts +0 -48
  514. package/dist/features/stores/components/StoreScopedSearch.d.ts +0 -17
  515. package/dist/features/stores/components/StoreScopedSearch.js +0 -27
  516. package/dist/seed/defaults/homepage-sections.d.ts +0 -2
  517. package/dist/seed/defaults/homepage-sections.js +0 -60
  518. package/dist/seed/factories/homepage-section.factory.d.ts +0 -10
  519. package/dist/seed/factories/homepage-section.factory.js +0 -13
  520. /package/dist/{features/search/types/index.js → _internal/shared/listing-types/spares/og.d.ts} +0 -0
@@ -0,0 +1,57 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /*
4
+ * WHY: 752 parts were reachable only by drilling classification -> code.
5
+ * `/parts` had no search input anywhere.
6
+ * WHAT: A search box over the `part` slice of the local index. Zero Firestore
7
+ * reads, and it resolves the code ambiguity in the result row.
8
+ *
9
+ * ## 🛑 The ambiguity is the feature, not a problem to hide
10
+ *
11
+ * `route-map.ts` explains why a code alone cannot be a URL: "`105` is a Metal
12
+ * Fight spin-track height, a bare number in Burst is a disc, and `1-60` is a
13
+ * Beyblade X ratchet." So the honest answer to "105" is THREE results, each
14
+ * naming its classification and each linking to the right two-segment path —
15
+ * not one result picked by whatever sorted first.
16
+ *
17
+ * That is exactly what the index already carries: the part source puts the
18
+ * classification in `detail` for precisely this reason, and derives the slug
19
+ * by splitting the `${slot}--${code}` document id, which is the one
20
+ * derivation guaranteed to agree with the page that exists.
21
+ *
22
+ * ## It does not replace the drill-down
23
+ *
24
+ * The classification grid stays. Browsing by "what kind of thing is this" is
25
+ * a different question from "where is the part I can already name", and the
26
+ * grid is the only one of the two that works when you do not know the word.
27
+ *
28
+ * @tag domain:parts
29
+ * @tag layer:feature
30
+ * @tag pattern:none
31
+ * @tag access:client
32
+ * @tag consumers:app/[locale]/parts/page.tsx
33
+ * @tag sideEffects:network
34
+ */
35
+ import React from "react";
36
+ import { Div, Input, Stack, Text, TextLink } from "../../../ui/index.js";
37
+ import { useSiteSearch } from "../../search/hooks/useSiteSearch.js";
38
+ /** Only this slice of the index. See `resolveEntity`'s `types` parameter. */
39
+ const PART_TYPES = ["part"];
40
+ /** Stable identity — a `useMemo` dependency inside the hook. */
41
+ const partLabel = () => "Parts";
42
+ export function PartsSearchBox({ indexEnabled, placeholder = "Search parts by name or code — RF, 105, Rubber Flat…", limit = 10, }) {
43
+ const [query, setQuery] = React.useState("");
44
+ const [active, setActive] = React.useState(false);
45
+ const { status, result } = useSiteSearch(query, {
46
+ active,
47
+ indexEnabled,
48
+ types: PART_TYPES,
49
+ label: partLabel,
50
+ });
51
+ const hits = result?.groups[0]?.hits ?? [];
52
+ const typed = query.trim().length > 0;
53
+ return (_jsxs(Stack, { gap: "sm", className: "min-w-0", children: [_jsx(Input, { type: "search", value: query, placeholder: placeholder, "aria-label": "Search parts", onFocus: () => setActive(true), onChange: (event) => {
54
+ setActive(true);
55
+ setQuery(event.target.value);
56
+ } }), typed && status === "loading" && _jsx(Text, { color: "muted", children: "Searching\u2026" }), typed && (status === "failed" || status === "disabled") && (_jsx(Text, { size: "sm", color: "muted", children: "Part search is unavailable right now \u2014 browse by classification below." })), typed && status === "ready" && hits.length === 0 && (_jsx(Text, { color: "muted", children: "No part matches that name or code." })), hits.length > 0 && (_jsx(Stack, { gap: "xs", className: "min-w-0", children: hits.slice(0, limit).map((hit) => (_jsxs(Div, { surface: "card", padding: "sm", rounded: "md", border: "subtle", children: [_jsx(TextLink, { href: hit.href, children: hit.title }), hit.detail && (_jsx(Text, { size: "xs", color: "muted", children: hit.detail }))] }, hit.id))) }))] }));
57
+ }
@@ -59,6 +59,45 @@ export declare const PART_SLOT_VALUES: {
59
59
  readonly BLADE: "blade";
60
60
  readonly RATCHET: "ratchet";
61
61
  readonly BIT: "bit";
62
+ readonly GT_CHIP: "gt-chip";
63
+ readonly GATINKO_CHIP: "gatinko-chip";
64
+ readonly BASE: "base";
65
+ readonly SUPERKING_CHIP: "superking-chip";
66
+ readonly DB_CORE: "db-core";
67
+ readonly RING: "ring";
68
+ readonly ARMOR_TIP: "armor-tip";
69
+ readonly FRAME: "frame";
70
+ readonly CHASSIS: "chassis";
71
+ readonly BU_BLADE: "bu-blade";
72
+ readonly QS_BLADE: "qs-blade";
73
+ readonly DRIVE_CHIP: "drive-chip";
74
+ readonly STORM_CHIP: "storm-chip";
75
+ readonly STRIKE_CHIP: "strike-chip";
76
+ readonly GRAVITY_RING: "gravity-ring";
77
+ readonly SPIRIT_SHIELD: "spirit-shield";
78
+ readonly SPIRIT_AXLE: "spirit-axle";
79
+ readonly DISC_INTEGRATED_DRIVER: "disc-integrated-driver";
80
+ readonly LOCK_CHIP: "lock-chip";
81
+ readonly MAIN_BLADE: "main-blade";
82
+ readonly ASSIST_BLADE: "assist-blade";
83
+ readonly OVER_BLADE: "over-blade";
84
+ readonly METAL_BLADE: "metal-blade";
85
+ readonly RATCHET_INTEGRATED_BLADE: "ratchet-integrated-blade";
86
+ readonly RATCHET_INTEGRATED_BIT: "ratchet-integrated-bit";
87
+ readonly WARRIOR_WHEEL: "warrior-wheel";
88
+ readonly ELEMENT_WHEEL: "element-wheel";
89
+ readonly LIGHT_WHEEL: "light-wheel";
90
+ readonly WHEEL: "wheel";
91
+ readonly SHOGUN_FACE_BOLT: "shogun-face-bolt";
92
+ readonly DOME_SPIN_TRACK: "dome-spin-track";
93
+ readonly EVOLUTION_GEAR: "evolution-gear";
94
+ readonly BIT_PROTECTOR: "bit-protector";
95
+ readonly WEIGHT: "weight";
96
+ readonly CORE: "core";
97
+ readonly SUPPORT_PARTS: "support-parts";
98
+ readonly SUB_ATTACK_RING: "sub-attack-ring";
99
+ readonly CEW: "cew";
100
+ readonly GEAR_CHIP: "gear-chip";
62
101
  };
63
102
  export type PartSlot = (typeof PART_SLOT_VALUES)[keyof typeof PART_SLOT_VALUES];
64
103
  /**
@@ -122,6 +161,55 @@ export declare const ALL_PART_SLOTS: readonly PartSlot[];
122
161
  */
123
162
  export declare function partSlotFromSegment(segment: string): PartSlot | null;
124
163
  /** One part. */
164
+ /**
165
+ * How much a given spec value is to be trusted, in the corpus's own
166
+ * vocabulary so nothing is lost in translation.
167
+ *
168
+ * `confirmed` — `FACT(PDB)`, verified against PlasticsDB's own part page, or
169
+ * a `[CONFIRMED CSn Case m]` citation in the case study.
170
+ * `fact` — a bare `FACT` tag, or a wiki infobox value.
171
+ * `inferred` — the source flags it as an inference.
172
+ * `estimated` — the source marks it approximate. 🛑 A `~` in a COLUMN HEADER
173
+ * marks the whole column, which is how gen3/gen4 write it; a
174
+ * per-cell check alone would publish 300+ estimates as facts.
175
+ */
176
+ export type PartSpecConfidence = "confirmed" | "fact" | "inferred" | "estimated";
177
+ /** One labelled specification row. */
178
+ export interface PartSpec {
179
+ /** "Weight", "Material", "Full width", "Stats", "WBO legality". */
180
+ label: string;
181
+ /** Verbatim from the source. Multi-valued cells are never resolved. */
182
+ value: string;
183
+ /** "g", "mm". Absent for a non-dimensional value. */
184
+ unit?: string;
185
+ /** Which extractor produced it, for the provenance footnote. */
186
+ source?: string;
187
+ confidence?: PartSpecConfidence;
188
+ }
189
+ /** One release of a part: which box, which bey, which vendor, which colour. */
190
+ export interface PartRelease {
191
+ /** "Takara Tomy", "Hasbro", "Sonokong", "Youngtoys". */
192
+ vendor: string;
193
+ /** The box code. `BX-00` is the wiki's marker for "no retail number". */
194
+ code?: string;
195
+ /** The Beyblade it came in. */
196
+ bey: string;
197
+ /** The set or multipack, when the bey shipped inside one. */
198
+ set?: string;
199
+ colourway?: string;
200
+ /** "G1 Prize", "CoroCoro Exclusive" — the channel, not the colour. */
201
+ distribution?: string[];
202
+ }
203
+ /** A distinct colourway, deduped on (colour, channel). */
204
+ export interface PartColourway {
205
+ /** "Red Ver.", "Bronze Ver.", "Supreme Dragon Ver.". */
206
+ colourway: string;
207
+ vendor: string;
208
+ code?: string;
209
+ distribution?: string;
210
+ /** The bey this colourway was released in. */
211
+ inBey: string;
212
+ }
125
213
  export interface PartGlossaryDocument extends BaseDocument {
126
214
  /** `${slot}--${codeOrSlug}` — both halves, because a code is not unique. */
127
215
  id: string;
@@ -148,11 +236,70 @@ export interface PartGlossaryDocument extends BaseDocument {
148
236
  * than a lookup table.
149
237
  */
150
238
  usedBy?: string[];
151
- /** Code, name and the spoken form of the code — feeds `searchTxt`. */
239
+ /** Code, name and the spoken form of the code. */
152
240
  aliases?: string[];
153
241
  /** Which extractor source contributed the row. */
154
242
  source?: string;
155
- searchTxt?: string[];
243
+ /**
244
+ * Labelled specification rows, ready to render.
245
+ *
246
+ * 🛑 ONE array rather than a dozen typed fields. Material, dimensions, spin
247
+ * direction, JP name, romaji, product code, release date, WBO legality and
248
+ * the 0–6 stat grid all render as "a labelled row" and none has a query, a
249
+ * sort, a filter or a format of its own. Twelve typed fields would be twelve
250
+ * projection-triage entries for zero behaviour; promote one the day a reader
251
+ * is named for it.
252
+ *
253
+ * 🛑 NEVER carries a `Weight` row when `weightG` is set. The page renders
254
+ * the weight as a badge, so a row too would show it twice and the two could
255
+ * disagree the moment either is edited. The generator enforces this and
256
+ * `verify-part-specs` asserts it.
257
+ */
258
+ specs?: PartSpec[];
259
+ /**
260
+ * One sentence per part, generated from the facts above.
261
+ *
262
+ * 🛑 GENERATED, NEVER COPIED. Every source page has an `== Description ==`
263
+ * section and lifting it is both a CC-BY-SA problem and the precise
264
+ * anti-pattern the competitor crawl recorded of a rival store — wiki bodies
265
+ * lifted verbatim, one shipping with the literal UI string "Add to
266
+ * Wishlist". What this replaces is worse than nothing SEO-wise: a template
267
+ * reading "{name} is a Beyblade {label}. See which models use it", identical
268
+ * across 752 pages, which made them compete with each other.
269
+ */
270
+ seoDescription?: string;
271
+ /**
272
+ * Which Beyblades and sets this part shipped in, first-seen order.
273
+ *
274
+ * Distinct from `usedBy`, and both are worth having: `usedBy` holds
275
+ * `modelComposition` IDS that resolve to our own category leaves, while this
276
+ * holds the wiki's PRODUCT names including sets and multipacks we have no
277
+ * leaf for. 10,723 references extracted across 2,008 pages.
278
+ */
279
+ shippedIn?: string[];
280
+ /** The per-release rows `shippedIn` and `colourways` are derived from. */
281
+ releases?: PartRelease[];
282
+ /**
283
+ * Colourways, with the channel each was released through.
284
+ *
285
+ * 🛑 Absent and empty mean different things. Absent = "we have not looked";
286
+ * `[]` with `colourwaysDocumented: true` = "a source asserts there are
287
+ * none". Without that distinction a part with one release and a part we
288
+ * never checked render identically, which is Root Cause #57's exact symptom.
289
+ */
290
+ colourways?: PartColourway[];
291
+ colourwaysDocumented?: boolean;
292
+ /**
293
+ * A mould revision changes the physical part — weight, burst resistance — so
294
+ * it is a DIFFERENT axis from colour and must not be folded into it.
295
+ */
296
+ hasMoldVariations?: boolean;
297
+ /** `/media/<slug>`. 🛑 Never a raw Storage host URL. */
298
+ image?: string;
299
+ /** The wiki page the photo came from — the CC-BY-SA attribution target. */
300
+ imageSourceUrl?: string;
301
+ /** "Read more on the Beyblade Wiki". Facts taken, prose theirs, link out. */
302
+ sourceUrl?: string;
156
303
  }
157
304
  /** One slot of one model's composition. */
158
305
  export interface ModelSlot {
@@ -229,7 +376,6 @@ export interface ModelCompositionDocument extends BaseDocument {
229
376
  source?: string;
230
377
  /** The named-model category this composition describes, when one exists. */
231
378
  categoryId?: string;
232
- searchTxt?: string[];
233
379
  }
234
380
  /** `(slot, code|name)` → document id. The ONE place this is composed. */
235
381
  export declare function partGlossaryId(slot: PartSlot, codeOrName: string): string;
@@ -27,6 +27,71 @@ export const PART_SLOT_VALUES = {
27
27
  BLADE: "blade",
28
28
  RATCHET: "ratchet",
29
29
  BIT: "bit",
30
+ /*
31
+ * ── 🛑 THE OTHER 39, ADDED 2026-10-20 FROM THE WIKI RE-CRAWL ─────────────
32
+ *
33
+ * The original 20 predate Gatinko, Sparking, Dynamite Battle, QuadDrive,
34
+ * QuadStrike, Burst Ultimate and the whole Beyblade X Custom line. These are
35
+ * not wiki noise — `case study/BEYBLADE MASTER REFERENCE.md` documents the
36
+ * STACK of each system, and every key below is a slot in one of them:
37
+ *
38
+ * GT / Gatinko GT Chip -> Layer Base -> Forge Disc -> Driver
39
+ * SK / Sparking Sparking Chip -> Layer Base -> Forge Disc -> Driver
40
+ * DB DB Core -> Armor -> Layer Ring -> Forge Disc -> Driver
41
+ * CX Lock Chip + Main Blade + Assist Blade -> Ratchet -> Bit
42
+ * CX Expand Lock Chip + Over Blade + Metal Blade + Assist Blade -> …
43
+ *
44
+ * Measured: the live `Category:Parts` holds 2,261 English pages against our
45
+ * 752 rows, and 569 of them carried a classification this union could not
46
+ * express — so they were unrepresentable rather than merely absent.
47
+ *
48
+ * 🛑 MAPPED, NOT DUPLICATED. `Forge Disc` is `disc`, `Armor` is `armour`,
49
+ * `Energy Layer` is `layer`, `Layer Base` is `base`, `Sparking Chip` is
50
+ * `superking-chip`. A second key for any of them would split one part
51
+ * family in half: the existing 752 rows in one, every new row in the other.
52
+ * The alias map lives in `scripts/lib/part-slot-vocab.mjs`, which is the
53
+ * SOURCE this union mirrors — the same contract the 20 above already have
54
+ * with `extract-part-composition.mjs`.
55
+ */
56
+ GT_CHIP: "gt-chip",
57
+ GATINKO_CHIP: "gatinko-chip",
58
+ BASE: "base",
59
+ SUPERKING_CHIP: "superking-chip",
60
+ DB_CORE: "db-core",
61
+ RING: "ring",
62
+ ARMOR_TIP: "armor-tip",
63
+ FRAME: "frame",
64
+ CHASSIS: "chassis",
65
+ BU_BLADE: "bu-blade",
66
+ QS_BLADE: "qs-blade",
67
+ DRIVE_CHIP: "drive-chip",
68
+ STORM_CHIP: "storm-chip",
69
+ STRIKE_CHIP: "strike-chip",
70
+ GRAVITY_RING: "gravity-ring",
71
+ SPIRIT_SHIELD: "spirit-shield",
72
+ SPIRIT_AXLE: "spirit-axle",
73
+ DISC_INTEGRATED_DRIVER: "disc-integrated-driver",
74
+ LOCK_CHIP: "lock-chip",
75
+ MAIN_BLADE: "main-blade",
76
+ ASSIST_BLADE: "assist-blade",
77
+ OVER_BLADE: "over-blade",
78
+ METAL_BLADE: "metal-blade",
79
+ RATCHET_INTEGRATED_BLADE: "ratchet-integrated-blade",
80
+ RATCHET_INTEGRATED_BIT: "ratchet-integrated-bit",
81
+ WARRIOR_WHEEL: "warrior-wheel",
82
+ ELEMENT_WHEEL: "element-wheel",
83
+ LIGHT_WHEEL: "light-wheel",
84
+ WHEEL: "wheel",
85
+ SHOGUN_FACE_BOLT: "shogun-face-bolt",
86
+ DOME_SPIN_TRACK: "dome-spin-track",
87
+ EVOLUTION_GEAR: "evolution-gear",
88
+ BIT_PROTECTOR: "bit-protector",
89
+ WEIGHT: "weight",
90
+ CORE: "core",
91
+ SUPPORT_PARTS: "support-parts",
92
+ SUB_ATTACK_RING: "sub-attack-ring",
93
+ CEW: "cew",
94
+ GEAR_CHIP: "gear-chip",
30
95
  };
31
96
  /**
32
97
  * Buyer-facing label per slot.
@@ -62,6 +127,47 @@ export const PART_SLOT_LABEL = {
62
127
  blade: "Blade",
63
128
  ratchet: "Ratchet",
64
129
  bit: "Bit",
130
+ // The 39 added 2026-10-20. Labels are the wiki's own `Classification=`
131
+ // spelling, which is also what a buyer sees printed in product listings.
132
+ "gt-chip": "GT Chip",
133
+ "gatinko-chip": "Gatinko Chip",
134
+ base: "Layer Base",
135
+ "superking-chip": "Superking Chip",
136
+ "db-core": "DB Core",
137
+ ring: "Layer Ring",
138
+ "armor-tip": "Armor Tip",
139
+ frame: "Frame",
140
+ chassis: "Chassis",
141
+ "bu-blade": "BU Blade",
142
+ "qs-blade": "QS Blade",
143
+ "drive-chip": "Drive Chip",
144
+ "storm-chip": "Storm Chip",
145
+ "strike-chip": "Strike Chip",
146
+ "gravity-ring": "Gravity Ring",
147
+ "spirit-shield": "Spirit Shield",
148
+ "spirit-axle": "Spirit Axle",
149
+ "disc-integrated-driver": "Disc-Integrated Driver",
150
+ "lock-chip": "Lock Chip",
151
+ "main-blade": "Main Blade",
152
+ "assist-blade": "Assist Blade",
153
+ "over-blade": "Over Blade",
154
+ "metal-blade": "Metal Blade",
155
+ "ratchet-integrated-blade": "Ratchet-Integrated Blade",
156
+ "ratchet-integrated-bit": "Ratchet-Integrated Bit",
157
+ "warrior-wheel": "Warrior Wheel",
158
+ "element-wheel": "Element Wheel",
159
+ "light-wheel": "Light Wheel",
160
+ wheel: "Wheel",
161
+ "shogun-face-bolt": "Shogun Face Bolt",
162
+ "dome-spin-track": "Dome Spin Track",
163
+ "evolution-gear": "Evolution Gear",
164
+ "bit-protector": "Bit Protector",
165
+ weight: "Weight",
166
+ core: "Core",
167
+ "support-parts": "Support Parts",
168
+ "sub-attack-ring": "Sub Attack Ring",
169
+ cew: "Customize Engine Weight",
170
+ "gear-chip": "Gear Chip",
65
171
  };
66
172
  /**
67
173
  * Which CATEGORY node a part of this classification is filed under.
@@ -123,6 +229,68 @@ export const PART_SLOT_CATEGORY = {
123
229
  blade: "category-x-blades",
124
230
  ratchet: "category-x-ratchets",
125
231
  bit: "category-x-bits",
232
+ /*
233
+ * ── The 39 added 2026-10-20 ──────────────────────────────────────────────
234
+ *
235
+ * 🛑 EVERY TARGET ALREADY EXISTS IN `category-forest.ts`. Verified against
236
+ * it rather than assumed: no new parent node is created here, so the forest
237
+ * is untouched, `buildCategoryTree` derives the same shape it already does,
238
+ * and the only change is which parent a part leaf nests under. Minting 39
239
+ * new nodes would be a taxonomy restructure — and the parts layer is moving
240
+ * out of categories in a follow-up plan anyway, so adding nodes to it now
241
+ * would be churn with a known expiry.
242
+ *
243
+ * Grouped by what the part IS, not by when we learned about it: the Burst
244
+ * chip/armour node already collects "small Burst component that is not a
245
+ * layer, disc or driver", which is exactly what GT/Gatinko/Superking/DB/
246
+ * QuadDrive chips are.
247
+ */
248
+ // Burst — layer stack components.
249
+ base: "category-burst-layers",
250
+ ring: "category-burst-layers",
251
+ frame: "category-burst-layers",
252
+ chassis: "category-burst-layers",
253
+ "bu-blade": "category-burst-layers",
254
+ "qs-blade": "category-burst-layers",
255
+ "gravity-ring": "category-burst-layers",
256
+ // Burst — chips, armour and the small bits that bolt onto a layer.
257
+ "gt-chip": "category-burst-chips-armour",
258
+ "gatinko-chip": "category-burst-chips-armour",
259
+ "superking-chip": "category-burst-chips-armour",
260
+ "db-core": "category-burst-chips-armour",
261
+ "armor-tip": "category-burst-chips-armour",
262
+ "drive-chip": "category-burst-chips-armour",
263
+ "storm-chip": "category-burst-chips-armour",
264
+ "strike-chip": "category-burst-chips-armour",
265
+ "spirit-shield": "category-burst-chips-armour",
266
+ "spirit-axle": "category-burst-chips-armour",
267
+ weight: "category-burst-chips-armour",
268
+ core: "category-burst-chips-armour",
269
+ // Burst — a driver with the disc moulded in is still a driver.
270
+ "disc-integrated-driver": "category-burst-drivers",
271
+ // Beyblade X — the CX Custom line, which has its own node.
272
+ "lock-chip": "category-x-custom-cx",
273
+ "main-blade": "category-x-custom-cx",
274
+ "assist-blade": "category-x-custom-cx",
275
+ "over-blade": "category-x-custom-cx",
276
+ "metal-blade": "category-x-custom-cx",
277
+ "gear-chip": "category-x-custom-cx",
278
+ // Beyblade X — integrated parts file under the half a buyer shops for.
279
+ "ratchet-integrated-blade": "category-x-blades",
280
+ "ratchet-integrated-bit": "category-x-bits",
281
+ // Metal Fight / Shogun Steel.
282
+ "warrior-wheel": "category-metal-fusion-wheels",
283
+ "element-wheel": "category-metal-fusion-wheels",
284
+ "light-wheel": "category-metal-fusion-wheels",
285
+ wheel: "category-metal-fusion-wheels",
286
+ "shogun-face-bolt": "category-metal-face-bolts",
287
+ "dome-spin-track": "category-metal-spin-tracks",
288
+ // Plastic Generation / HMS.
289
+ "sub-attack-ring": "category-original-attack-rings",
290
+ "evolution-gear": "category-original-engine-gears",
291
+ "bit-protector": "category-original-bit-chips",
292
+ cew: "category-original-weight-disks",
293
+ "support-parts": "category-original-parts",
126
294
  };
127
295
  /** Every slot key, for an index page that must not hand-write the list. */
128
296
  export const ALL_PART_SLOTS = Object.values(PART_SLOT_VALUES);
@@ -169,6 +337,22 @@ export function partGlossaryId(slot, codeOrName) {
169
337
  export const LISTING_TYPE_HAS_COMPOSITION = {
170
338
  standard: true,
171
339
  auction: true,
340
+ /*
341
+ * 🛑 FALSE, and this is the one entry worth arguing for.
342
+ *
343
+ * `spares` is tempting to set true — it is the most part-shaped type in the
344
+ * union — and it would be a worse version of the exact defect this map's
345
+ * docblock records. A spare attack ring IS a part; it is not the assembly
346
+ * the composition describes. True would give an attack ring a "Parts" tab
347
+ * whose contents are an attack ring, a weight disk and a blade base: one
348
+ * level deeper into wrong than the poster was.
349
+ *
350
+ * The reverse direction is the useful one and it is phase F: a spare links
351
+ * UP to its glossary entry via `sparePartGlossaryId`, and that entry lists
352
+ * the models the part fits. "What is this a part of" is a real question; "what
353
+ * parts is this part made of" is not.
354
+ */
355
+ spares: false,
172
356
  "pre-order": true,
173
357
  "prize-draw": true,
174
358
  classified: true,
@@ -4,6 +4,7 @@
4
4
  * Data access layer for payout documents in Firestore.
5
5
  * Handles seller payout requests and admin payout processing.
6
6
  */
7
+ import type { JsonValue } from "../../../schemas/types";
7
8
  import { BaseRepository, parseSieveDateValue, type SieveModel, type FirebaseSieveResult } from "../../../providers/db-firebase";
8
9
  import type { DocumentReference } from "firebase-admin/firestore";
9
10
  import type { PayoutDocument, PayoutPlain, PayoutCreateInput, PayoutRefundDeduction, PayoutStatus, PayoutUpdateInput } from "../schemas";
@@ -51,6 +52,20 @@ export declare class PayoutRepository extends BaseRepository<PayoutDocument> {
51
52
  */
52
53
  protected piiFields: readonly ["sellerEmail", "upiId"];
53
54
  protected piiIndexMap: Record<string, string>;
55
+ /**
56
+ * Admin search by seller name/email, without decryption.
57
+ *
58
+ * 🛑 THIS IS THE ONE THAT MATTERS FOR THE TESTER HARNESS. `payouts` is
59
+ * SEED_TRANSACTIONAL: it cascades on `storeId` whenever its store is
60
+ * wiped, then gets RE-SEEDED from `appkit/src/seed/payouts-seed-data.ts`.
61
+ * The seed file has no `sellerTokensIndex` field — only this hook produces
62
+ * one — so a one-shot backfill script would have been silently undone by
63
+ * the very next tester run. Routing through `applyWriteHooks` means the
64
+ * reseed writes through `createWithId`, which calls this hook, which
65
+ * regenerates the index — so the field is never actually "missing after a
66
+ * wipe", because the wipe is always followed by the write that restores it.
67
+ */
68
+ protected buildTokensIndexFor(data: Record<string, JsonValue>): Record<string, string[]> | null;
54
69
  /**
55
70
  * The base hook, plus the nested objects it cannot see.
56
71
  *
@@ -4,6 +4,7 @@
4
4
  * Data access layer for payout documents in Firestore.
5
5
  * Handles seller payout requests and admin payout processing.
6
6
  */
7
+ import { buildTokensIndex } from "../../../security/blind-index-tokens.js";
7
8
  import { BaseRepository, prepareForFirestore, parseSieveDateValue, } from "../../../providers/db-firebase/index.js";
8
9
  import { PAYOUT_COLLECTION, PAYOUT_FIELDS, PAYOUT_TRACKED_FIELDS, createPayoutId } from "../schemas/index.js";
9
10
  import { withHistory } from "../../../_internal/shared/history/index.js";
@@ -69,6 +70,26 @@ export class PayoutRepository extends BaseRepository {
69
70
  maskedPayouts(docs) {
70
71
  return docs.map((d) => this.maskedPayout(d));
71
72
  }
73
+ /**
74
+ * Admin search by seller name/email, without decryption.
75
+ *
76
+ * 🛑 THIS IS THE ONE THAT MATTERS FOR THE TESTER HARNESS. `payouts` is
77
+ * SEED_TRANSACTIONAL: it cascades on `storeId` whenever its store is
78
+ * wiped, then gets RE-SEEDED from `appkit/src/seed/payouts-seed-data.ts`.
79
+ * The seed file has no `sellerTokensIndex` field — only this hook produces
80
+ * one — so a one-shot backfill script would have been silently undone by
81
+ * the very next tester run. Routing through `applyWriteHooks` means the
82
+ * reseed writes through `createWithId`, which calls this hook, which
83
+ * regenerates the index — so the field is never actually "missing after a
84
+ * wipe", because the wipe is always followed by the write that restores it.
85
+ */
86
+ buildTokensIndexFor(data) {
87
+ const sellerName = typeof data.sellerName === "string" ? data.sellerName : undefined;
88
+ const sellerEmail = typeof data.sellerEmail === "string" ? data.sellerEmail : undefined;
89
+ if (!sellerName && !sellerEmail)
90
+ return null;
91
+ return { sellerTokensIndex: buildTokensIndex(sellerName, sellerEmail) };
92
+ }
72
93
  /**
73
94
  * The base hook, plus the nested objects it cannot see.
74
95
  *
@@ -8,7 +8,7 @@ const __P = {
8
8
  const __O = {
9
9
  hidden: "overflow-hidden",
10
10
  };
11
- const CLS_BREADCRUMB_LINK = "hover:text-primary-600 transition-colors";
11
+ const CLS_BREADCRUMB_LINK = "hover:text-primary-600 dark:hover:text-primary-400 transition-colors";
12
12
  const CLS_PREORDER_BADGE = "inline-block rounded-full bg-indigo-100 dark:bg-indigo-900/30 px-[var(--appkit-space-2-5)] py-[var(--appkit-space-0-5)] text-indigo-700 dark:text-indigo-300";
13
13
  const CLS_STATUS_BADGE = "inline-block rounded-full bg-warning-surface dark:bg-warning-surface px-[var(--appkit-space-2-5)] py-[var(--appkit-space-0-5)] text-warning dark:text-warning";
14
14
  import { ROUTES } from "../../../next/routing/route-map.js";
@@ -17,16 +17,17 @@ import { formatCurrency, roundRupees } from "../../../utils/number.formatter.js"
17
17
  import { normalizeRichTextHtml } from "../../../utils/string.formatter.js";
18
18
  import { safeDisplayName } from "../../../security/index.js";
19
19
  import { ProgressBarFill } from "../../../ui/components/ProgressBarFill.js";
20
- import { Button, Container, Div, GatedPrice, PricesOnly, Heading, Main, Nav, RichText, Row, Section, Span, Stack, Text, Ul, Li, Dl, Dt, Dd, } from "../../../ui/index.js";
20
+ import { Button, Container, Div, GatedPrice, PricesOnly, Heading, Main, Nav, RichText, Row, Section, Span, Stack, Text, Ul, Li, SpecTable, } from "../../../ui/index.js";
21
21
  import { PreOrderDetailView } from "../../products/components/PreOrderDetailView.js";
22
22
  import { PreOrderBottomActions } from "./PreOrderBottomActions.js";
23
23
  import { ProductTabsShell } from "../../products/components/ProductTabsShell.js";
24
- import { CustomSectionTabContent } from "../../products/components/CustomSectionTabContent.js";
24
+ import { toCustomSectionTabs } from "../../products/components/CustomSectionTabContent.js";
25
25
  import { PreOrderActionsClient } from "./PreOrderActionsClient.js";
26
26
  import { ProductGalleryClient } from "../../products/components/ProductGalleryClient.js";
27
27
  import { ProductFeatureBadges } from "../../products/components/ProductFeatureBadges.js";
28
28
  import { isFinalSale } from "../../products/constants/final-sale.js";
29
29
  import { FeatureBadgeList } from "../../products/components/FeatureBadge.js";
30
+ import { productImageUrls } from "../../products/schemas/firestore.js";
30
31
  import { ShareButton } from "../../products/components/ShareButton.js";
31
32
  import { SublistingCarouselSection } from "../../products/components/SublistingCarouselSection.js";
32
33
  import { HistoryTracker } from "../../history/components/HistoryTracker.js";
@@ -86,8 +87,12 @@ export async function PreOrderDetailPageView({ id, initialPreOrder, onReserveNow
86
87
  const currency = p.currency || getDefaultCurrency();
87
88
  const title = String(p.title ?? p.name ?? "Pre-Order Item");
88
89
  const price = typeof p.price === "number" ? p.price : null;
89
- const images = Array.isArray(p.images)
90
- ? p.images
90
+ // `images` is `ProductImage[]` since A6 — `productImageUrls` is the one
91
+ // normaliser (it also accepts the legacy `string[]`). Casting it to
92
+ // `string[]` handed the gallery objects and rendered a placeholder.
93
+ const galleryUrls = productImageUrls(p.images);
94
+ const images = galleryUrls.length > 0
95
+ ? galleryUrls
91
96
  : typeof p.mainImage === "string"
92
97
  ? [p.mainImage]
93
98
  : [];
@@ -142,9 +147,6 @@ export async function PreOrderDetailPageView({ id, initialPreOrder, onReserveNow
142
147
  const specs = Array.isArray(p.specifications)
143
148
  ? p.specifications
144
149
  : [];
145
- const customSections = Array.isArray(p.customSections)
146
- ? p.customSections
147
- : [];
148
150
  const descriptionHtml = toDescriptionHtml(p.description);
149
151
  const sublistingCategoryId = typeof p.sublistingCategoryId === "string" ? p.sublistingCategoryId : null;
150
152
  const groupId = typeof p.groupId === "string" ? p.groupId : null;
@@ -156,11 +158,7 @@ export async function PreOrderDetailPageView({ id, initialPreOrder, onReserveNow
156
158
  ]);
157
159
  return (_jsxs(Main, { children: [_jsx(HistoryTracker, { productId: String(p.id ?? p.slug ?? ""), productType: "preorder", snapshot: {
158
160
  title: typeof p.title === "string" ? p.title : undefined,
159
- thumb: typeof p.mainImage === "string"
160
- ? p.mainImage
161
- : Array.isArray(p.images) && typeof p.images[0] === "string"
162
- ? p.images[0]
163
- : undefined,
161
+ thumb: typeof p.mainImage === "string" ? p.mainImage : images[0],
164
162
  price: typeof p.price === "number" ? p.price : undefined,
165
163
  storeId: typeof p.storeId === "string" ? p.storeId : undefined,
166
164
  storeName: typeof p.storeName === "string" ? p.storeName : undefined,
@@ -168,9 +166,5 @@ export async function PreOrderDetailPageView({ id, initialPreOrder, onReserveNow
168
166
  ? () => (_jsx(SublistingCarouselSection, { sublistingCategoryId: sublistingCategoryId, currentListingId: String(product.id) }))
169
167
  : undefined, renderGroupSection: groupId
170
168
  ? () => (_jsx(ShowGroupSection, { groupId: groupId, currentSlug: String(p.slug ?? product.id), isParent: isGroupParent, groupTitle: groupTitle }))
171
- : undefined, renderTabs: () => (_jsx(ProductTabsShell, { descriptionContent: descriptionHtml ? (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm sm:prose max-w-none dark:prose-invert", className: "text-[var(--appkit-color-text-muted)]" })) : undefined, specsContent: specs.length > 0 ? (_jsx(Dl, { divide: "subtle", rounded: "xl", border: "subtle", className: "overflow-hidden", children: specs.map((s, i) => (_jsxs(Row, { gap: "md", oddEven: "zebra", surface: "default", padding: "inline", children: [_jsx(Dt, { className: "w-36 flex-shrink-0", color: "primary", weight: "medium", children: s.name }), _jsxs(Dd, { className: "flex-1", color: "muted", children: [s.value, s.unit ? ` ${s.unit}` : ""] })] }, i))) })) : undefined, customTabs: customSections.map((s) => ({
172
- id: s.id,
173
- label: s.title,
174
- content: _jsx(CustomSectionTabContent, { section: s }),
175
- })) })), renderBuyBar: () => (_jsx(PreOrderBuyBarPanel, { reserveTarget: reserveTarget, reservedCount: reservedCount, progressPct: progressPct, productId: String(product.id), price: price, currency: currency, depositAmount: depositAmount, depositPercent: depositPercent, isCancellable: isCancellable, tags: tags, onReserveNow: onReserveNow })), renderRelated: () => (_jsxs(Stack, { gap: "xl", children: [_jsx(GroupedListingsCarousel, { groups: groups }), _jsx(RelatedItemsSection, { relatedItems: relatedItems, relatedByBrand: relatedByBrand, relatedByTags: relatedByTags, relatedByStore: relatedByStore, categoryLabel: categoryName || category || undefined, brandLabel: brand || undefined, storeLabel: storeName || undefined })] })) }), _jsx(PreOrderBottomActions, { price: price, currency: currency })] })] }));
169
+ : undefined, renderTabs: () => (_jsx(ProductTabsShell, { descriptionContent: descriptionHtml ? (_jsx(RichText, { html: descriptionHtml, proseClass: "prose prose-sm sm:prose max-w-none dark:prose-invert", className: "text-[var(--appkit-color-text-muted)]" })) : undefined, specsContent: specs.length > 0 ? (_jsx(SpecTable, { rows: specs })) : undefined, customTabs: toCustomSectionTabs(p.customSections) })), renderBuyBar: () => (_jsx(PreOrderBuyBarPanel, { reserveTarget: reserveTarget, reservedCount: reservedCount, progressPct: progressPct, productId: String(product.id), price: price, currency: currency, depositAmount: depositAmount, depositPercent: depositPercent, isCancellable: isCancellable, tags: tags, onReserveNow: onReserveNow })), renderRelated: () => (_jsxs(Stack, { gap: "xl", children: [_jsx(GroupedListingsCarousel, { groups: groups }), _jsx(RelatedItemsSection, { relatedItems: relatedItems, relatedByBrand: relatedByBrand, relatedByTags: relatedByTags, relatedByStore: relatedByStore, categoryLabel: categoryName || category || undefined, brandLabel: brand || undefined, storeLabel: storeName || undefined })] })) }), _jsx(PreOrderBottomActions, { price: price, currency: currency })] })] }));
176
170
  }
@@ -232,5 +232,5 @@ export function PreOrdersIndexListing({ initialData, categorySlug, brandName })
232
232
  ] }), totalPages > 1 && (_jsx(StickyToolbar, { offset: "header+pagination", tone: "translucent", border: true, padding: "toolbar", children: _jsx(Row, { justify: "center", children: _jsx(Pagination, { currentPage: page, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) }) })), _jsx(Div, { padding: "y-lg", children: isLoading ? (_jsx(Grid, { cols: "cards", gap: "md", children: Array.from({ length: 10 }).map((_, i) => (_jsxs(Div, { className: `${__O.hidden} animate-pulse`, border: "subtle", rounded: "xl", children: [_jsx(Div, { className: "aspect-square", surface: "subtle" }), _jsxs(Stack, { className: `${__P.p3}`, gap: "sm", children: [_jsx(Div, { className: "h-3 w-3/4", surface: "subtle", rounded: "default" }), _jsx(Div, { className: "h-3 w-1/2", surface: "subtle", rounded: "default" }), _jsx(Div, { className: "h-4 w-1/3", surface: "subtle", rounded: "default" }), _jsx(Div, { className: "h-8", surface: "subtle", rounded: "default" })] })] }, i))) })) : preOrders.length === 0 ? (_jsx(Text, { paddingY: "3xl", color: "muted", size: "sm", align: "start", children: "No pre-orders found." })) : view === "list" ? (_jsx(Stack, { className: "divide-y divide-zinc-100 divide-[var(--appkit-color-border-subtle)]", border: "subtle", rounded: "xl", children: preOrders.map((product) => (_jsx(MarketplacePreorderCard, { product: product, variant: "list", hrefBuilder: (p) => String(ROUTES.PUBLIC.PRE_ORDER_DETAIL(p.id)), onAddToCart: handleAddToCart, wishlistActions: wishlistActions, selectable: selection.isSelecting, isSelected: selection.isSelected(product.id), onSelect: (id) => selection.toggle(id) }, product.id))) })) : (_jsx(Grid, { cols: "cards", gap: "md", children: preOrders.map((product) => (_jsx(MarketplacePreorderCard, { product: product, variant: "grid", hrefBuilder: (p) => String(ROUTES.PUBLIC.PRE_ORDER_DETAIL(p.id)), onAddToCart: handleAddToCart, wishlistActions: wishlistActions, selectable: selection.isSelecting, isSelected: selection.isSelected(product.id), onSelect: (id) => selection.toggle(id) }, product.id))) })) }), _jsx(CompareOverlay, { isOpen: compareIds.length > 0, productIds: compareIds, productType: "preorder", onClose: () => {
233
233
  setCompareIds([]);
234
234
  selection.clearSelection();
235
- }, onRemove: (id) => setCompareIds((ids) => ids.filter((i) => i !== id)) }), _jsx(FilterDrawer, { open: filterOpen, onOpen: openFilters, onClose: () => setFilterOpen(false), onApply: applyFilters, onReset: onFilterClear, activeCount: filterActiveCount, hideTrigger: true, children: _jsx(PreOrderFilters, { table: pendingTable, currencyPrefix: "\u20B9", categoryOptions: categoryOptions, brandOptions: brandOptions }) }), _jsx(LoginRequiredModal, { isOpen: modalOpen, onClose: closeModal, message: modalMessage })] }));
235
+ }, onRemove: (id) => setCompareIds((ids) => ids.filter((i) => i !== id)), onAdd: (id) => setCompareIds((ids) => (ids.includes(id) ? ids : [...ids, id])) }), _jsx(FilterDrawer, { open: filterOpen, onOpen: openFilters, onClose: () => setFilterOpen(false), onApply: applyFilters, onReset: onFilterClear, activeCount: filterActiveCount, hideTrigger: true, children: _jsx(PreOrderFilters, { table: pendingTable, currencyPrefix: "\u20B9", categoryOptions: categoryOptions, brandOptions: brandOptions }) }), _jsx(LoginRequiredModal, { isOpen: modalOpen, onClose: closeModal, message: modalMessage })] }));
236
236
  }
@@ -79,9 +79,32 @@ export interface PriceIndexToolResponse {
79
79
  truncated: boolean;
80
80
  minConfidentSamples: number;
81
81
  }
82
+ /**
83
+ * The competitor-crawl band for one leaf. Mirrors `PriceIndexMarketRow`.
84
+ *
85
+ * Every field but `median` and `categoryId` is optional because the crawl
86
+ * genuinely did not measure them everywhere, and an absent figure must render
87
+ * as absent. See `price-bands.md`: "a band with `n=2` is not evidence".
88
+ */
89
+ export interface PriceIndexMarketRowView {
90
+ categoryId: string;
91
+ median: number;
92
+ p25?: number;
93
+ p75?: number;
94
+ sampleSize?: number;
95
+ asOf?: string;
96
+ soldOutShare?: number;
97
+ source?: string;
98
+ inherited: boolean;
99
+ viaCategoryId?: string;
100
+ viaName?: string;
101
+ taxBasis: string;
102
+ }
82
103
  export interface PriceIndexToolViewProps {
83
104
  /** Seeded from `?q=` so a shared link reproduces the lookup. */
84
105
  initialQuery?: string;
85
106
  initialData?: PriceIndexToolResponse | null;
107
+ /** `siteSettings.search?.indexEnabled`. Read as `!== false`. */
108
+ searchIndexEnabled?: boolean;
86
109
  }
87
- export declare function PriceIndexToolView({ initialQuery, initialData }: PriceIndexToolViewProps): React.JSX.Element;
110
+ export declare function PriceIndexToolView({ initialQuery, initialData, searchIndexEnabled, }: PriceIndexToolViewProps): React.JSX.Element;